-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC for while let
statement
#214
Conversation
Personally, the biggest motivating reason to do this is consistency (last paragraph of the motivation). Though @cmr did say he's wanted a construct like this in the past. |
While I'm not personally against this and I love If we're adding this because we want to align more with Swift and make the Swift -> Rust transition easier for users (let's keep in mind that Swift will be a major language, by Apple fiat), that might be a good enough reason. |
Yeah, I didn't state it outright in the document, but as long as we're borrowing |
FWIW I just did a quick search for
This would become while let Some(ref cmnt) = self.next_comment() {
// ...
} Same thing again at line 2654 in the same file.
would become while let Some((i, c)) = chars.next() {
// ...
} Same pattern again at line 462 in the same file.
would become while let Some(piece) = parser.next() {
// ...
} And so on. You get the idea. There are more spots that could be updated if we supported alternatives in while let Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') = it.peek().map(|x| x.val1()) {
it.next();
} However, I didn't propose alternatives here, because it looks kind of weird. Same reason I didn't put them in |
RFC alternatives section updated for pattern alternatives. |
Oops, wrong button. Thanks for making that so easy, GitHub. |
What I like about this is that I think it would encourage a prevalent use of
vs
How viable is the |
@arcto Well, we'd rather people just use |
@reem Good point. Perhaps data on the prevalence of applicable places in current codebases could be used as basis for a decision. Even though Swift is rather new are there any indicators on the feature's reception over there? |
@kballard Your last two examples (from That said, I like the RFC (mainly for consistency with
loop {
let ei = match cur_eis.pop() {
None => break, /* for each Earley Item */
Some(ei) => ei,
}
...
}; could be rewritten as while let Some(ei) = cur_eis.pop() {
...
} A lot of these follow a pattern of |
I'd like to have this. It follows logically from I think disjunctive patterns should eventually be extended to |
```rust | ||
// the match here is so `for` can accept an rvalue for the iterator, | ||
// and was used in the "real" desugaring version. | ||
match &mut BODY { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be match &mut EXPR {
.
I think the point @arcto makes about makes about If we disallow Big 👍 |
6357402
to
e0acdf4
Compare
+1. Along with the consistency argument (which I think is a good one), we have several places in Servo that would benefit from this, like this code that calls loop {
match self.from_client.recv() {
Load(load_data, start_chan) => {
self.load(load_data, start_chan)
}
Exit => {
break
}
}
} which could be rewritten as: while let Load(load_data, start_chan) = self.from_client.recv() {
self.load(load_data, start_chan)
} |
I'm for this, even just for the consistency argument but also because I think it does make some code much more readable. |
FYI: C++ allows a simple variable definition in the condition part of #include <iostream>
using namespace std;
int main() {
if (int x = 10 % 2) {
cout << "10 % 2 == " << x << endl;
}
if (int x = 10 % 3) {
cout << "10 % 3 == " << x << endl;
}
switch (int x = 10 % 2) {
case 0: cout << "zero: " << x << endl; break;
case 1: cout << "one: " << x << endl; break;
}
switch (int x = 10 % 3) {
case 0: cout << "zero: " << x << endl; break;
case 1: cout << "one: " << x << endl; break;
}
int i = 9;
while (int r = ++i % 3) {
cout << i << ": " << r << endl;
}
for (int j = 1, k = 1; int diff = j*j - 3*k; j++,k++) {
cout << "j: " << j << ", k: " << k << ", diff: " << diff << endl;
}
return 0;
}
On the other hand, the D programming language doesn't allow such a definition in the condition part of any of |
This RFC has been accepted. |
* Cleanup * More
Summary
Introduce a new
while let PAT = EXPR { BODY }
construct. This allows for using a refutable patternmatch (with optional variable binding) as the condition of a loop.
Motivation
Just as
if let
was inspired by Swift, it turns out Swift supportswhile let
as well. This wasnot discovered until much too late to include it in the
if let
RFC. It turns out that this sort oflooping is actually useful on occasion. For example, the desugaring
for
loop is actually a varianton this; if
while let
existed it could have been implemented to mapfor PAT in EXPR { BODY }
to(note that the non-desugared form of
for
is no longer equivalent).More generally, this construct can be used any time looping + pattern-matching is desired.
This also makes the language a bit more consistent; right now, any condition that can be used with
if
can be used withwhile
. The newif let
adds a form ofif
that doesn't map towhile
.Supporting
while let
restores the equivalence of these two control-flow constructs.Detailed design
while let
operates similarly toif let
, in that it desugars to existing syntax. Specifically,the syntax
desugars to
Just as with
if let
, an irrefutable pattern given towhile let
is considered an error. This islargely an artifact of the fact that the desugared
match
ends up with an unreachable pattern,and is not actually a goal of this syntax. The error may be suppressed in the future, which would be
a backwards-compatible change.
Just as with
if let
,while let
will be introduced under a feature gate (namedwhile_let
).Drawbacks
Yet another addition to the grammar. Unlike
if let
, it's not obvious how useful this syntax willbe.
Alternatives
As with
if let
, this could plausibly be done with a macro, but it would be ugly and produce baderror messages.
while let
could be extended to support alternative patterns, just as match arms do. This is notpart of the main proposal for the same reason it was left out of
if let
, which is that a) it looksweird, and b) it's a bit of an odd coupling with the
let
keyword as alternatives like this aren'tgoing to be introducing variable bindings. However, it would make
while let
more general and ableto replace more instances of
loop { match { ... } }
than is possible with the main design.Unresolved questions
None.