From ffb35708fc99acbeacdd6c9c7c5b0624d19c3cde Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Wed, 27 Aug 2014 15:27:56 -0700 Subject: [PATCH 1/3] RFC for `while let` statement --- active/0000-while-let.md | 78 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 active/0000-while-let.md diff --git a/active/0000-while-let.md b/active/0000-while-let.md new file mode 100644 index 00000000000..aaafae5d20c --- /dev/null +++ b/active/0000-while-let.md @@ -0,0 +1,78 @@ +- Start Date: 2014-08-27 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary + +Introduce a new `while let PAT = EXPR { BODY }` construct. This allows for using a refutable pattern +match (with optional variable binding) as the condition of a loop. + +# Motivation + +Just as `if let` was inspired by Swift, it turns out Swift supports `while let` as well. This was +not discovered until much too late to include it in the `if let` RFC. It turns out that this sort of +looping is actually useful on occasion. For example, the desugaring `for` loop is actually a variant +on this; if `while let` existed it could have been implemented to map `for PAT in EXPR { BODY }` 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 { + i => { + while let Some(PAT) = i.next() { + BODY + } + } +} +``` + +(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 with `while`. The new `if let` adds a form of `if` that doesn't map to `while`. +Supporting `while let` restores the equivalence of these two control-flow constructs. + +# Detailed design + +`while let` operates similarly to `if let`, in that it desugars to existing syntax. Specifically, +the syntax + +```rust +['ident:] while let PAT = EXPR { + BODY +} +``` + +desugars to + +```rust +['ident:] loop { + match EXPR { + PAT => BODY, + _ => break + } +} +``` + +Just as with `if let`, an irrefutable pattern given to `while let` is considered an error. This is +largely 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 (named `while_let`). + +# Drawbacks + +Yet another addition to the grammar. Unlike `if let`, it's not obvious how useful this syntax will +be. + +# Alternatives + +As with `if let`, this could plausibly be done with a macro, but it would be ugly and produce bad +error messages. + +# Unresolved questions + +None. From e909a9d621cb5f8d7771308079948f489841c61f Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Wed, 27 Aug 2014 17:11:31 -0700 Subject: [PATCH 2/3] Update `while let` with pattern alternatives. --- active/0000-while-let.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/active/0000-while-let.md b/active/0000-while-let.md index aaafae5d20c..ea68b468c0a 100644 --- a/active/0000-while-let.md +++ b/active/0000-while-let.md @@ -73,6 +73,12 @@ be. As with `if let`, this could plausibly be done with a macro, but it would be ugly and produce bad error messages. +`while let` could be extended to support alternative patterns, just as match arms do. This is not +part of the main proposal for the same reason it was left out of `if let`, which is that a) it looks +weird, and b) it's a bit of an odd coupling with the `let` keyword as alternatives like this aren't +going to be introducing variable bindings. However, it would make `while let` more general and able +to replace more instances of `loop { match { ... } }` than is possible with the main design. + # Unresolved questions None. From c1dd38e9b603cfece9ed7c60bf0dc57e3d7edcd2 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Fri, 29 Aug 2014 11:54:02 -0700 Subject: [PATCH 3/3] s/BODY/EXPR/ --- active/0000-while-let.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/active/0000-while-let.md b/active/0000-while-let.md index ea68b468c0a..5c016233dff 100644 --- a/active/0000-while-let.md +++ b/active/0000-while-let.md @@ -17,7 +17,7 @@ on this; if `while let` existed it could have been implemented to map `for PAT i ```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 { +match &mut EXPR { i => { while let Some(PAT) = i.next() { BODY