Suppose we require a keyword – say var – before all binding patterns. This results in having to write things like for (&(var x1, var y1, var z1), &(var x2, var y2, var z2)) in points.iter().tuple_windows() {},
which is quite a bit more verbose than the current for (&(x1, y1, z1), &(x2, y2, z2)) in points.iter().tuple_windows() {}.
Not to mention you’ll have to write letvar x = 0; just to declare a variable, unless you redesign the language to allow you to just write var x = 0 (and if you do that, you’ll also have to somehow support a coherent way to express ifletSome(x) = arr.pop() {} and letSome(x) = arr.pop() else {todo!()}).
Suppose we require a keyword – say const – before all value-matching patterns that look like variables. Then, what’s currently
and you always run the risk of forgetting a const and accidentally binding a new match-all variable named None – the main footgun that syntactically distinguishing binding and value-matching patterns was meant to avoid in the first place.
Suppose we require a sigil such as $ before one type of pattern. Probably the best solution in my opinion, but that’s one symbol that can no longer be used for other things in a pattern context. Also, if you’re already using sigils before variable names for other purposes (I’ve been sketching out a language where a pointer variable $x can be auto-dereferenced by writing x), doubling up is really unpleasant.
…So I can understand why Rust chose to give the same, most concise possible syntax for both binding and value-matching patterns. At least compiler warnings (unused, non-snake-case variables) are there to provide some protection from accidentally turning one into the other.
One mistake they did unfortunately ship though is bind patterns that look like variable names.
There was a recent langdev Stack Exchange question about this very topic. It’s a bit trickier to design than it might seem at first.
Suppose we require a keyword – say
var
– before all binding patterns. This results in having to write things likefor (&(var x1, var y1, var z1), &(var x2, var y2, var z2)) in points.iter().tuple_windows() {}
,which is quite a bit more verbose than the current
for (&(x1, y1, z1), &(x2, y2, z2)) in points.iter().tuple_windows() {}
.Not to mention you’ll have to write
let var x = 0;
just to declare a variable, unless you redesign the language to allow you to just writevar x = 0
(and if you do that, you’ll also have to somehow support a coherent way to expressif let Some(x) = arr.pop() {}
andlet Some(x) = arr.pop() else {todo!()}
).Suppose we require a keyword – say
const
– before all value-matching patterns that look like variables. Then, what’s currentlymatch (left.next(), right.next()) { (Some(l), Some(r)) => {} (Some(l), None) => {} (None, Some(r)) => {} (None, None) => {} }
turns into either the inconsistently ugly
match (left.next(), right.next()) { (Some(l), Some(r)) => {} (Some(l), const None) => {} (const None, Some(r)) => {} (const None, const None) => {} }
or the even more verbose
match (left.next(), right.next()) { (const Some(l), const Some(r)) => {} (const Some(l), const None) => {} (const None, const Some(r)) => {} (const None, const None) => {} }
and you always run the risk of forgetting a
const
and accidentally binding a new match-all variable namedNone
– the main footgun that syntactically distinguishing binding and value-matching patterns was meant to avoid in the first place.Suppose we require a sigil such as
$
before one type of pattern. Probably the best solution in my opinion, but that’s one symbol that can no longer be used for other things in a pattern context. Also, if you’re already using sigils before variable names for other purposes (I’ve been sketching out a language where a pointer variable$x
can be auto-dereferenced by writingx
), doubling up is really unpleasant.…So I can understand why Rust chose to give the same, most concise possible syntax for both binding and value-matching patterns. At least compiler warnings (unused, non-snake-case variables) are there to provide some protection from accidentally turning one into the other.
As in using consts (or variables you think are consts) as refutable patterns? Yeah this was an oversight I’m sure.
One option is an edition change requiring a
const
keyword, soRight now they use a lint to try to warn the dev though.