-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Braceless Else on Braced Expressions #1686
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
Closed
Closed
Changes from 2 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
f36ac77
Add "Braceless Else on Braced Expressions".
phoenixenero 7fca911
Clarify text on Braceless else on Braced expressions
phoenixenero a1f1a74
Further clarified text and removed superfluous examples.
phoenixenero f163908
Added additional clarification and tweaked examples a bit.
phoenixenero 77fe245
Removed superfluous sentences and stated the advantages better.
phoenixenero 258bf75
Added 2nd-level headings and more examples.
phoenixenero 0a0cbee
Improved phrasing and fixed awkward sentences.
phoenixenero f015ab7
Expanded alternatives and tweaked drawback examples.
phoenixenero File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
- Feature Name: Braceless Else on Braced Expressions | ||
- Start Date: 2016-07-25 | ||
- RFC PR: | ||
- Rust Issue: | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
Make braces around `else` body optional on single expressions that require braces to increase | ||
brevity. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
Rust doesn't require parenthesis around the condition of an `if`, but does require braces around | ||
the bodies of `if` and `else`. | ||
|
||
This is good because it avoids the ambiguity and the potential for mistakes around nested `if`s and | ||
`else`s that exists in other C-family languages. | ||
|
||
But this can be too verbose when writing stuff like `match` statements inside `else` clauses. | ||
|
||
```rust | ||
if foo() { | ||
do_this() | ||
} else if bar() { | ||
do_this_other_thing() | ||
} else { | ||
match baz() { | ||
A => do_that(), | ||
B => do_the_other(), | ||
_ => do_something_else() | ||
} | ||
} | ||
``` | ||
|
||
A better solution would be to *omit* the braces around the body of an `else`. | ||
|
||
``` | ||
if foo() { | ||
do_this() | ||
} else if bar() { | ||
do_this_other_thing() | ||
} else match baz() { | ||
A => do_that(), | ||
B => do_the_other(), | ||
_ => do_something_else() | ||
} | ||
``` | ||
|
||
However, there's another problem. If we do this for *any* time of expression or statement, a | ||
potential bug may occur. | ||
|
||
``` | ||
if foo() { | ||
do_this() | ||
} else | ||
do_that(); | ||
do_the_other(); // oops, this line always runs | ||
``` | ||
|
||
A solution is to limit this behavior to only *single expressions which itself require braces*. This | ||
includes `match`, `for`, `loop`, and `while`. | ||
|
||
An interesting observation is that this type of syntax already exists in the form of an `else if` | ||
clause. Writing the following code: | ||
|
||
```rust | ||
if foo() { | ||
do_this() | ||
} else if bar() { | ||
do_that() | ||
} else if baz() { | ||
do_this_other_thing(); | ||
} | ||
``` | ||
|
||
is the same as writing: | ||
|
||
```rust | ||
if foo() { | ||
do_this() | ||
} else { | ||
if bar() { | ||
do_that() | ||
} else { | ||
if baz() { | ||
do_this_other_thing(); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
This proposal can be seen as the natural progression from the previous syntax to the other | ||
expressions. | ||
|
||
# Detailed design | ||
[design]: #detailed-design | ||
|
||
Braces can only be omitted around the body of an `else` if the body is a single expression which | ||
itself requires braces. | ||
|
||
So these examples are valid: | ||
|
||
``` | ||
if foo() { | ||
do_this() | ||
} else match bar() { | ||
A => do_that(), | ||
B => do_the_other() | ||
} | ||
|
||
if foo() { | ||
do_this() | ||
} else loop { | ||
do_this_forever(); | ||
} | ||
|
||
if foo() { | ||
do_this() | ||
} else for x in 0..10 { | ||
do_this_ten_times(); | ||
} | ||
``` | ||
|
||
This example however is not: | ||
|
||
``` | ||
if foo() { | ||
do_this() | ||
} else do_that(); | ||
``` | ||
|
||
An extra `else` clause should be declared as a syntax error if the previous `else <expr>` has no | ||
`else` clause. | ||
|
||
This is invalid: | ||
|
||
``` | ||
if foo() { | ||
do_this() | ||
} else match bar() { | ||
A => do_that(), | ||
B => do_the_other() | ||
} else { | ||
// syntax error | ||
} | ||
``` | ||
|
||
as it's equivalent to: | ||
|
||
``` | ||
if foo() { | ||
do_this() | ||
} else { | ||
match bar() { | ||
A => do_that(), | ||
B => do_the_other() | ||
} else { | ||
// syntax error | ||
} | ||
} | ||
``` | ||
|
||
As of writing this includes all expressions except `if`. | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
- This syntax may look foreign to newcomers and may lead to mistaken assumptions such as: | ||
|
||
``` | ||
if foo() { | ||
do_this() | ||
} else match bar() { | ||
A => do_that(), | ||
B => do_the_other(), | ||
_ => do_something_else() | ||
} else { | ||
// syntax error | ||
} | ||
``` | ||
|
||
There's no solution for this, other than allowing `else` clauses on these expressions. For the | ||
previous example, `match` *does* have a sort of `else` clause in the form of an `_ => ...` match. | ||
So something like: | ||
|
||
``` | ||
if foo() { | ||
do_this() | ||
} else match bar() { | ||
A => do_that(), | ||
B => do_the_other() | ||
} else { // hypothetical syntax | ||
do_something_else() | ||
} | ||
``` | ||
|
||
should theoretically work. However this does not exist yet in current Rust and is outside the | ||
scope of this proposal. | ||
|
||
# Alternatives | ||
[alternatives]: #alternatives | ||
|
||
None. | ||
|
||
# Unresolved questions | ||
[unresolved]: #unresolved-questions | ||
|
||
None. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
How often does something like this actually occur?