4 ms·
I would check out: http://pzol.github.io/getting_rusty/posts/20140417_destructuring_in_rust/ http://pzol.github.io/getting_rusty/posts/20140417_destructu... Fo
by bjz_ 13y ago
I would check out: http://pzol.github.io/getting_rusty/posts/20140417_destructuring_in_rust/ http://pzol.github.io/getting_rusty/posts/20140417_destructu...
For example:
struct Foo { x: (uint, uint), y: uint }
let foo = Foo { x: (1, 2), y: 3 };
let Foo { x: tuple @ (a, b), .. } = foo; // => a == 1; b == 2; tuple == (1, 2)
In terms of mut:
let (mut x, ref y, &z) = (1, 2, &3);
x = 2; // reassignment is ok, because we bound `x` as mutable
x += *y; // we bound `y` as a reference, so it must be derefed first
x += z; // we used a `&` pattern to get the value stored in the reference, so
// derefing is not necessary
*y += 1; // this would not compile, because y is immutable
- acqq 13y agoThanks. Now I see that my preferred approach would collide with current declaration logic of having mut ref and & in front of the names. Otherwise it would seem possible foo := Foo { x: (1, 2), y: 3 }; Foo { x: tuple @ (a, b), .. } := foo; ( x: mut, y: ref, &z ) := (1, 2, &3); xx: mut := 33; I see that having "x: mut" has one character more than "mut x" but I don't believe it makes the text less readable, quite the contrary because it's certainly less surprising when everything that describes the variable follows the ":" Thanks a lot, I've certainly learned more about Rust this way.
- bjz_ 13y agoShowing let bindings with their explicit type declarations might help: let mut x: int = 2; let x: &mut int = &mut 2; let (mut x, ref y, &z): (int, int, &int) = (1, 2, &3); The pattern binding goes to the left of the `:`, and the input type goes to the right. Also note that you can pattern match on types too: let (mut x, ref y, &z): (_, int, &_) = (1, 2, &3);
- acqq 13y agoThanks, if _ is allowed as the type, why are explicit types written at all? Is the last example equivalent to let (mut x, ref y, &z): (_, _, &_) = (1, 2, &3); and can we go even further let (mut x, ref y, &z) = (1, 2, &3); If we can, when do we actually need specifying the types? To do the type conversion or what? Probably because I don't know Haskell (sorry) but I still imagine x y and z as names and even mut, ref and & as the "access" specifications, which define somehow the "type" of x y and z and not the type the thing accessed with the given name.
- bjz_ 13y agoI might not have been clear enough. I was just trying to show how the current syntax fits in with `:`, and why your suggestions for `: mut` would not fit with that. All of these are valid Rust code: let (mut x, ref y, &z): (int, int, &int) = (1, 2, &3); let (mut x, ref y, &z): (_, _, &_) = (1, 2, &3); let (mut x, ref y, &z) = (1, 2, &3); The types are still the same in each case. No conversions or dynamic typing is happening in any of them - they are all statically typed. Rust, like Haskell and ML, uses an advanced form of type reconstruction called Hindley-Milner[0] type inference. This is a constraint solving algorithm that can deduce types from very little information. Sometimes you do need to add some annotations though to help the inference along a little, but that is very rare (although more common in Rust than in Haskell or ML). The grammar could be expressed as: 'let' <pattern> (':' <type>)? '=' <expr> Where `<type>` is the type of the expression to the right of the `=`. As I said before: in practice it is very rare to explicitly annotate a `let` binding. [0]: http://en.wikipedia.org/wiki/Hindley-Milner http://en.wikipedia.org/wiki/Hindley-Milner
- gnuvince 13y agoPretty sure your parser would need unbounded lookahead to support this syntax.
- acqq 13y agoWhat do you think how the parser parses anything on the left side, e.g. in C: *( arraybase + f1( d ) * f2( e, f ) + f3( g ) ) = x;
- pcwalton 13y agoThe issue is that "expression" is the same nonterminal in C, whereas "expression" and "pattern" are separate nonterminals.
- acqq 13y agoIn C a difference still exists between a lvalue and a rvalue. Even if you can unify something at one level, you have to generate completely different code. C++ is even harder. So I can imagine something can be done when there would be an intention, probably something would have to be a bit more unified. But I guess nobody even tried. BTW, I really like the basic goals of Rust, namely making something directly linkable with C but having as much as possible safety and more modern features. And I appreciate the work of the developers of Rust. Even introductory materials would benefit by promoting what we can do that wasn't as safe to be done in C.