Lifetimes - implicit/explicit semantics for how long a name is considered alive, whereas in C++ there would be a delete or falling out of scope. Borrowing - I still don't understand how or why a non-reference is implicitly consumed by passing it (read-only intention) by value(?) to another function and then can't be used again. Pony does explicit consumption. There seems to be a need for training classes in Rust that…
> I still don't understand how or why a non-reference is implicitly consumed by passing it (read-only intention) by value(?) to another function and then can't be used again. By default the value is moved in Rust, just like with std::move in C++17, which you say you know. This is to avoid performance issues when you pass complex structures, such as vectors, around. If you want to copy your value, you have to call .co…
Deriving Traits in Rust with Procedural Macros
11–20 of 31 posts
Re: Deriving Traits in Rust with Procedural Macros
#12Lifetimes - implicit/explicit semantics for how long a name is considered alive, whereas in C++ there would be a delete or falling out of scope. Borrowing - I still don't understand how or why a non-reference is implicitly consumed by passing it (read-only intention) by value(?) to another function and then can't be used again. Pony does explicit consumption. There seems to be a need for training classes in Rust that…
> I still don't understand how or why a non-reference is implicitly consumed by passing it (read-only intention) by value(?) to another function and then can't be used again. By default the value is moved in Rust, just like with std::move in C++17, which you say you know. This is to avoid performance issues when you pass complex structures, such as vectors, around. If you want to copy your value, you have to call .co…
That explains the move but not mandating explicit verbosity for a common case. Pony, for example, has consume to end the lifetime of a variable, .
Re: Deriving Traits in Rust with Procedural Macros
#13Earlier quoted context omitted.
Procedural macros are something you more or less never need to write in application code, but they add tremendous power to libraries
Which doesn't make it easier, since you might want to structure part of you application code as a reusable library.
Re: Deriving Traits in Rust with Procedural Macros
#14Lifetimes - implicit/explicit semantics for how long a name is considered alive, whereas in C++ there would be a delete or falling out of scope. Borrowing - I still don't understand how or why a non-reference is implicitly consumed by passing it (read-only intention) by value(?) to another function and then can't be used again. Pony does explicit consumption. There seems to be a need for training classes in Rust that…
It's not the surprise-copy-horror you'd expect, because there are no copy constructors, and nothing large is ever copied implicitly (you have to call `.clone()` or implement `Copy` trait for a type).
The move semantics can ensure there exists only one owning pointer to each object. It can be statically known who owns the object, and most importantly, who has to free it.
Re: Deriving Traits in Rust with Procedural Macros
#15Lifetimes - implicit/explicit semantics for how long a name is considered alive, whereas in C++ there would be a delete or falling out of scope. Borrowing - I still don't understand how or why a non-reference is implicitly consumed by passing it (read-only intention) by value(?) to another function and then can't be used again. Pony does explicit consumption. There seems to be a need for training classes in Rust that…
> Borrowing The way I think about this (which isn't quite how rust seems to) is that every value (including references) is always destroyed by passing it to a function, but gets implicitly copied if (arg is copyable && arg is referenced below). Eg: T a = mkT() # create value foo(&a) # create and immediately destroy/pass reference bar(a) # => bar(copy(&a)) # create-and-pass copy baz(a) # last use, so dont bother copyi…
I am not sure what you are trying to say. This:
bar(a) # => bar(copy(&a)) # create-and-pass copy
baz(a) # last use, so dont bother copying
is not possible in Rust if a's type is not a copy type. a will be moved when calling bar, so trying to pass it to baz will result in a compiler error.The story is quite simple: a value is always moved in a function call, unless it is a copy type (the type implements the Copy trait). When the type is a copy type, a bit-wise copy is made. References are not special: immutable references are copy types. Mutable references are not copy types (otherwise, they could be aliased).
You can find an overview of all copy types in the standard library in the implementations section of the Copy trait:
https://doc.rust-lang.org/beta/std/marker/trait.Copy.html#fo...
Re: Deriving Traits in Rust with Procedural Macros
#16Rust is morphing into a complexity beast that rivals C++. When the cognitive load require to read and write Rust code far exceeds that required of other, more popular languages, the future does not look rosy.
Procedural macros are something you more or less never need to write in application code, but they add tremendous power to libraries
Re: Deriving Traits in Rust with Procedural Macros
#17Earlier quoted context omitted.
Which doesn't make it easier, since you might want to structure part of you application code as a reusable library.
It is entirely optional. I use Rust for two years now and work on a few things (biggest one around 10kLOC). I didn’t even read the Macro section in my books yet. Because I didn’t need to.
Re: Deriving Traits in Rust with Procedural Macros
#18Rust is morphing into a complexity beast that rivals C++. When the cognitive load require to read and write Rust code far exceeds that required of other, more popular languages, the future does not look rosy.
Ownership and the borrows checker may have a steep learning curve, but are not very complex. The rules are quite simple, the learning curve is steep because most programmers do not typically think about ownership (though they should).
(In my experience in teaching Rust, things like trait impl coherency rules, object safety, and finding a good balance between static and dynamic polymorphism are much harder for students than understanding the ownership system.)
Re: Deriving Traits in Rust with Procedural Macros
#19Lifetimes - implicit/explicit semantics for how long a name is considered alive, whereas in C++ there would be a delete or falling out of scope. Borrowing - I still don't understand how or why a non-reference is implicitly consumed by passing it (read-only intention) by value(?) to another function and then can't be used again. Pony does explicit consumption. There seems to be a need for training classes in Rust that…
In Rust there's a move or a falling out of scope. Lifetimes are passive, and just describe the connection between references so that the compiler can check that they don't become dangling when values are destroyed in essentially the same places as C++ would destroy them.
> Borrowing - I still don't understand how or why a non-reference is implicitly consumed by passing it (read-only intention) by value(?) to another function and then can't be used again. Pony does explicit consumption.
Rust had a more pony-like model with annotations and different modes many years ago, but the model was unnecessarily complicated and was simplified to a "everything is pass-by-value" one:
- http://smallcultfollowing.com/babysteps/blog/2011/12/08/why-...
- http://smallcultfollowing.com/babysteps/blog/2012/10/01/move...
Things to know:
- Rust has no copy constructors (but does have a "this can be safely semantically duplicated by memcpy" marker trait (Copy), which cannot run arbitrary code. See https://stackoverflow.com/a/31013156/1256624 and https://stackoverflow.com/a/24253573/1256624.)
- A "move" is a memcpy (bitwise copy) of a value to a new location, where the source becomes inaccessible at compile time
- A "read-only" T is a separate type &T, which is a value in its own right (and &_ implements Copy, so can be passed-by-value multiple times without explicit copies).
- Every value of type T is always a fully-fledged T, with all of T's operations available
- Parameters of type T (e.g. fn f(x: T)) are thus full values
- For an arbitrary type T, there's no way to (implicitly) copy values of type T, so the only way to call a function with a T parameter is to have the callee take ownership/responsibility for the caller's T value (i.e. move it into the call)
Re: Deriving Traits in Rust with Procedural Macros
#20Earlier quoted context omitted.
Procedural macros are something you more or less never need to write in application code, but they add tremendous power to libraries
Deriving typeclass implementations is something I do all the time in regular application code (in Scala), once you're used to it it gives you a lot of safety and expressive power. It sounds like Rust would benefit from some kind of record system / generic representation of traits (like we get from Shapeless in Scala) so that generic trait deriving could be written in normal code without needing macros.
That said, an equivalent library in Rust would be very useful.