This feature would allow the use of fields and existing variables to be destructed into while destructing tuples.
Motivation
There is currently no way to destructure tuples into preexisting variables (including struct fields) so do get that affect it is necessary to create new bindings and then assign again, each in turn, to the variables that you want. This works but doesn't show the intent to the best degree.
So a destructure is able to be done without a let statement. It can be more along the line of an assignment instead of only an initialization.
Object destructuring should also be supported, for parity and simplicity of teaching.
Reference-level explanation
So a new kind of left hand side of an assignment would be allowed that doesn't have a prefixed let. This sort of left hand side would destructure a tuple into the named locations (not just variables, could be fields).
Drawbacks
It makes the language more complicated
Can technically do this with macros or similar
Rationale and alternatives
This brings the destructing up to parity in assignment along with variable defining.
Prior art
JS destructing assignment does allow for this sort of assignment.
Unresolved questions
Should mixing and matching names that have/haven't been declared yet be allowed. If they are a possible solution could be (a.b, let c) = foo() since that makes it clear which ones are being declared/assigned.
Why the limit to just tuple patterns, it seems like also supporting object patterns (and all other forms of patterns) as mentioned in the prior art would be more consistent
struct A {
b: i32,
c: i32
}
struct D {
e: i32,
f: i32,
}
fn foo() -> D;
fn main() {
let a: A;
D { e: a.c, f: a.b } = foo();
}
Disclaimer: I'm not part of the relevant team, just a bystander.
The title of the pre-RFC is not entirely clear as to what the goal is. Your goal seems to be about initializing a struct via destructuring. The way you're proposing to do it uses an existing variable, but that's the how, not the what.
From the title, I'd expect things like the following to be discussed too:
which currently can be written as a simple let Foo(a) = foo(), but in principle, would be allowed by this proposal (at least under its current title). And if not, why not should be discussed too.
From a language perspective, at least as I understand it, what happens with patterns is that they can define bindings. Struct members are not bindings. This is a significant change for what can happen with patterns. Another significant difference is the lack of a let in that assignment.
FWIW, I think the following, which work today, are not too cumbersome as an alternative.
let a = match foo() {
(b, c) => A { b, c }
};
or
let a = match foo() {
D { e: c, d: b } => A { b, c }
};
You seem to want to introduce the production $pat = $expr for expressions, with the semantics "exhaustively match $expr against $pat, and treat each atomic pattern in $pat as a preexisting place."
This is... basically fine. Except that the lhs of = can be a complex expression, which would require embedding the expression grammar into the pattern grammar... which seems really really bad.
These trivially have the same shape. You might be able to argue that it could always parse as ambiguous, as they always have the same shape between expr and pattern, but then it becomes data-dependant as to what the correct parse is: it depends on the type of twpe::variant being a type or a function. That's no good.
I've definitely wanted something like this, but this isn't a tenable way to get there.
This syntax seems ambiguous to me, in a pattern; it could mean assignment to an existing location, or matching equal to the value in that location. I'd like to avoid that ambiguity.
Right, I suppose that even if it returned a mut ref you'd have to deref it to get a place to which to assign.
I think that's still "grammatically correct" though which means it might mess with macros to change how it parses.
I'm having trouble thinking of an actual example that would be accepted through typeck which would be ambiguous with a pattern assign, so it could theoretically be possible to parse as "expr or pattern" then use the correct case grammatically, but I'm far from being able to show one way or another.
But then it also raises the question of patterns in other locations or requires making the "pattern in expr position" grammar distinct from other pattern positions.