What is the difference between Double Colons and Periods? - rust

I am very new to Rust, and the :: operator is new to me. I can tell that :: and . both have their own use cases, and I want to understand on a conceptual level where/why code would use :: vs . or vice versa. Apologies if this is a really basic question!

:: is a path divider. It's mostly used for navigating submodules to express paths that lead to types, traits, modules and stand-alone functions (aka items):
// import everything in the collections module
use std::collections::*;
// specify a fully-qualified type without imports
let map = std::collections::HashMap::new();
// call a stand-alone function
let mut iter = std::iter::once(1);
. is used for navigating data. Specifically, that means accessing members of structs and calling methods:
// call a method
vec.sort();
// access a field of a struct
let bar = foo.bar;

. is really syntactic sugar for :: when talking about (structs, enums, traits):
A call to MyStruct::foo(&my_struct) would be evaluated from my_struct.foo().
You can mostly substitute them when working with what was mentioned above.
Also, :: is used as a "namespace" accessor, for navigatring through rust modules. For example for referring to a method in a nested submodule system:
std::collections::HashMap::get
As a note here, full submodule paths cannot be accessed in any other way with ..

Related

Inner constructor in Julia with different name than the struct

I saw this construction in rationals.jl, and I am trying to understand it. I can write
struct Bar
y
global func(x) = new(x)
end
Then if I try:
a = Bar()
I get an error. It is like func is now an inner constructor. And I can actually use it by writing:
a = func(2)
If I remove the keyword global, I can't use this inner constructor anymore. What is going on? Why is global there, and could I use the inner constructor somehow without it (perhaps by qualifying the name)?
How can the inner constructor have a different name than the struct itself? What, in fact, is an inner constructor?
TL/DR
An inner constructor is a method of the struct type (i.e., (::Type{Bar})(...) which has access to new. You can put arbitrary method definitions inside a struct -- there is no technical requirement to only have inner constructors -- but this is only useful in rare cases.
Long version
This is a rare case that the manual doesn't even cover explicitely (and I long didn't know was legal at all). In my understanding, two rules apply:
Inside the struct definition, and only there, you are allowed to use new.
If any inner constructor method is defined, no default constructor method is provided: it is presumed that you have supplied yourself with all the inner constructors you need.
However, nothing requires the inner constructor to be a method of the struct type! Instead you may actually define arbitrary methods.
And then, scoping applies. With a "regular" inner constructor, what you get is a method for Type{Bar}. This requires no global, as the type is present in outer scope.
In your case, without the global, func is local and so there is no constructor accessible at all outside the struct definition. This makes little sense. The global function definition is something that can be useful in rare cases when you want to prevent direct construction of values of you type, but only allow conversion. I have seen this kind of pattern:
struct Baz
Base.reinterpret(::Type{Baz}, ...) = new(...)
end
This adds a (globally available) method to reinterpret, the only entry point to constructing Bazes. Putting it inside the struct is necessary, as at some place you need to create the object and thus require access to new.

Generating paths in submodule context given path in parent module context

I am creating an attribute macro that can be invoked with (a path to) some type amongst its attributes:
#[my_macro(path::to::SomeType)]
This macro generates a module, within which the specified type is to be used:
mod generated {
use path::to::SomeType;
}
However, from within that generated module, the path as provided may no longer be correct:
if the path is prefixed with ::, it remains correct—I can determine this within the proc macro;
otherwise, if the path starts with an identifier that is in a prelude (such as that of an external crate), it remains correct—I can't see any way to determine this within the proc macro;
otherwise it must now be prefixed with super:: for resolution to succeed.
Of course, I could require users of the macro to provide a path that will be correct from within the generated module, but that would not be very ergonomic.
Instead, I'm currently generating a type alias within the parent module:
type __generated_SomeType = path::to::SomeType;
mod generated {
use super::__generated_SomeType as SomeType;
}
However this is not only a tad clunky, but it furthermore pollutes the parent namespace.
Is there a better way?
I don't think there's a satisfying solution. But there's an alternative, and a way to improve your current approach.
The alternative is to use a const item:
const _: () = {
// ... your generated code here
};
It can still cause name collisions with items from the parent scope, but at least the generated items aren't visible outside of the const. This is what most macro authors do.
If you don't want to do that, you can go with your current approach, but you should add #[doc(hidden)] to the __generated_SomeType type, so it doesn't show up in documentation. Also, you should use an import instead of a type alias to support generic types, as suggested by #ChayimFriedman:
#[doc(hidden)]
use path::to::SomeType as __generated_SomeType;
I was just about to suggest combining these to approaches by putting a module inside a const item, but it doesn't work:
const _: () = {
use path::to::SomeType as __generated_SomeType;
mod generated {
// doesn't work :(
use super::__generated_SomeType as SomeType;
}
};
Rust complains that __generated_SomeType doesn't exist in the parent module.

Does a standard exist for variable names used left of a require()?

A simple question: I do not understand if a standard exists for variable names to be used left of require()'s, and if it does, what does it require: Uppercase or lowercase (camelcase) variable names?
To be clearer:
myImage = require('./image');
or
MyImage = require('./image');
?
I ask since required modules always return objects, so they can be used as Classes or Objects...
There is no requirement for the name of any variable in JavaScript except the rules defined in this answer. Some JavaScript frameworks have naming conventions, but these do not borrow from any native JavaScript behaviour.
However, usually you will see JS code with classes having capitalised pascal-case names (MyClass) and everything else is camel-case (anObject). I suggest that you abide this general standard in your own code so that it is easier for others to reason with.
This means that when you require you should employ the above naming convention according to what it is that you are requireing:
// CommonJS
let MyClass = require('./MyClass')
let utilMethod = require('./MyClass/utilMethod')
// ES6
import MyClass, { utilMethod } from 'MyClass';

How to provide and consume require.js modules in scala.js (and extending classes)

I'm doing this Ensime package for Atom.io https://github.com/ensime/ensime-atom and I've been thinking about the possibility to use scala.js instead of writing Coffeescript.
Atom is a web based editor which is scripted with js and is node.js based. A plugin/package defines it's main entry point by pointing out a javascript object with a few specific.
I figured I should start out simple and try using scala.js replacing the simplest coffeescript file I have:
{View} = require 'atom-space-pen-views'
# View for the little status messages down there where messages from Ensime server can be shown
module.exports =
class StatusbarView extends View
#content: ->
#div class: 'ensime-status inline-block'
initialize: ->
serialize: ->
init: ->
#attach()
attach: =>
statusbar = document.querySelector('status-bar')
statusbar?.addLeftTile {item: this}
setText: (text) =>
#text("Ensime: #{text}").show()
destroy: ->
#detach()
As you can see this exports a require.js module and is a class extending a class fetched with require as well.
Sooo.
I'm thinking I'd just use Dynamic for the require dep as I've seen on SO How to invoke nodejs modules from scala.js?:
import js.Dynamic.{global => g}
import js.DynamicImplicits._
private[views] object SpacePen {
private val spacePenViews = require("atom-space-pen-views")
val view = spacePenViews.view
}
But if I wanted to type the super-class, could I just make a facade-trait and do asInstanceOf?
Secondly, I wonder how I can export my class as a node module. I found this:
https://github.com/rockymadden/scala-node/blob/master/main/src/main/coffeescript/example.coffee
Is this the right way? Do I need to do the sandboxing? Couldn't I just get moduleimported from global and write module.exports = _some_scala_object_?
I'm also wondering how I could extend existing js classes. The same problem as asked here, but I don't really understand the answer:
https://groups.google.com/forum/#!topic/scala-js/l0gSOSiqubs
My code so far:
private[views] object SpacePen {
private val spacePenViews = js.Dynamic.global.require("atom-space-pen-views")
type View = spacePenViews.view
}
class StatusBarView extends SpacePen.View {
override def content =
super.div()
}
gives me compile errors that I can't extend sealed trait Dynamic. Of course.
Any pointers highly appreciated!
I'm not particularly expert in Node per se, but to answer your first question, yes -- if you have a pointer to a JS object, and you know the details of its type, you can pretty much always define a facade trait and asInstanceOf to use it. That ought to work.
As for the last bit, you basically can't extend JS classes in Scala.js -- it just doesn't work. The way most of us get around that is by defining implicit classes, or using implicit def's, to get the appearance of extending without actually doing so.
For example, given JS class Foo, I can write
implicit class RichFoo(foo:Foo) {
def method1() = { ... }
}
This is actually a wrapper around Foo, but calling code can simply call foo.method1() without worrying about that detail.
You can see this approach in action very heavily in jquery-facade, particularly in the relationship between JQuery (the pure facade), JQueryTyped (some tweaked methods over JQuery to make them work better in Scala), and JQueryExtensions (some higher-level functions built around JQuery). These are held together using implicit def's in package.scala. As far as calling code is concerned, all of these simply look like methods on JQuery.

In Groovy, can I override java-style casting syntax on POJO classes?

I would like to be able to use plain java-style implicit/explicit casting instead of asType overrides so that sources written in Java work properly. I've overridden asType on String similarly to the approach suggested in How to overload some Groovy Type conversion for avoiding try/catch of NumberFormatException? like:
oldAsType = String.metaClass.getMetaMethod("asType", [Class] as Class[])
String.metaClass.asType = {Class typ ->
if (Foo.class.isAssignableFrom(typ)) {
Foo.myCast(delegate)
} else {
oldAsType.invoke(delegate,typ)
}
}
I'd like all of these options to work:
// groovy
String barString
Foo foo = barString asType(Foo.class) // asType works but
Foo foo = barString // implicit cast fails
Foo foo = (Foo) barString // explicit cast fails
The latter two fail because groovy is using DefaultTypeTransformation.castToType, which doesn't attempt to invoke new Foo() unless the object to be cast is either one of a slew of special cases or is some sort of Collection type.
Note that the solution Can I override cast operator in Groovy? doesn't solve the issue because the code that is doing the casting is regular Java code that I cannot alter, at least not at the source code level. I'm hoping that there is either a secret hook into casting or a way to override the static castToType method (in a Java class, called by another Java class - which Can you use Groovy meta programming to override a private method on a Java class says is unsupported)... or some other clever approach I haven't thought of.
Edit: The question is about using Java-style casting syntax, essentially to use groovy facilities to add an autoboxing method. Groovy calls this mechanism "casting," for better or worse (see DefaultTypeTransformation.castToType as referenced above). In particular, I have replaced an enum with a resourced class and want to retain JSON serialization. Groovy's JSON package automatically un/marshals enum values of instance members to strings and I'm trying to make the replacement class serialize compatibly with a minimal changes to the source code.
Part of the problem here is you are confusing conversion with casting. Using the "as" operator is not the same thing as imposing a cast. They seem similar, but they serve separate purposes.
Foo foo = (Foo) barString
That doesn't say something like "create a Foo out of barString". That says "Declare a reference named foo, associate the static type Foo with that reference and then point that reference at the object on the heap that the reference barString currently points to.". Unlike languages like C++, Groovy and Java do not allow you to ever get in a situation where a reference points at an object that is of a type that is incompatible with the reference's type. If you ever got into a situation where a Foo reference was pointing to a String on the heap, that would represent a bug in the JVM. It cannot be done. You can come up with ways to create Foo objects out of String objects, but that isn't what the code above is about.
The answer appears to be "no". Absent a rewrite of the DefaultTypeTransformation.castToType to allow for this sort of metaprogramming, the implication is to use another implementation strategy or use a different language.

Resources