I disagree with the idea that the more general solution is unambiguously better. We already have the most general tool -- match
. What we want is to restrict a power of match
to get lighter syntax, that still covers many use-cases.
let .. else
is more general, but also more verbose and more complicated. The most substantial difference is you don't need to come up with a name for a binding to use ?:
. It is restricted to Try
(which wraps a single value), so it can be an expression. In contrast, let..else
either needs to be a new kind of statement, or, (in expr is pat
proposals) it needs changes to how name bindings fundamentally work (ie, switch from "binding is defined in the subtree of the syntax tree" to "binding is defined in the dominated expressions").
EDIT: this fundamentally more complex, non-expression desugaring is probably what is called magic by @Aloso.
For comparison, here are all constructs together for the simple case:
for line in buf_read.lines() {
let line = line ?: continue; // works only for `Try` types
let Ok(line) = line else { continue };
let line = match line { Ok(it) => it, _ => continue };
let line = if let Ok(it) = line { it } else { continue };
}
Here is a (bad) example of using expression capabilities of ?:
for line in buf_read.lines() {
process(line ?: continue); // works only for `Try` types
process({ let Ok(line) = line else { continue }; line });
process(match line { Ok(it) => it, _ => continue });
process(if let Ok(it) = line { it } else { continue });
}
Finally, there's a constructed example which is much shorter with ?:
:
foo ?: bar ?: baz ?: return
The question is, which proportion of cases, covered by let..else
, is also covered by ?:
? For example, all examples in this comment on the let..else RFC are actually covered by ?:
.
To clarify, I don't really have an opinion of which syntax strikes the better trade-off, if..else or ?:
. My personal gut feeling is that we might need both ?:
and expr is pat
.