-
Notifications
You must be signed in to change notification settings - Fork 535
WIP: Patterns chapter #284
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,7 +67,7 @@ while i < 10 { | |
|
||
> **<sup>Syntax</sup>** | ||
> [_PredicatePatternLoopExpression_] : | ||
> `while` `let` _Pattern_ `=` [_Expression_]<sub>except struct expression</sub> | ||
> `while` `let` [_Pattern_] `=` [_Expression_]<sub>except struct expression</sub> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
> [_BlockExpression_] | ||
|
||
A `while let` loop is semantically similar to a `while` loop but in place of a | ||
|
@@ -213,5 +213,6 @@ expression `()`. | |
|
||
[_Expression_]: expressions.html | ||
[_BlockExpression_]: expressions/block-expr.html | ||
[_Pattern_]: patterns.html | ||
|
||
[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,32 @@ | ||
# `match` expressions | ||
|
||
> **<sup>Syntax</sup>** | ||
> _MatchExpression_ : | ||
> `match` [_Expression_]<sub>_except struct expression_</sub> `{` | ||
> [_InnerAttribute_]<sup>\*</sup> | ||
> _MatchArms_<sup>?</sup> | ||
> `}` | ||
> | ||
> _MatchArms_ : | ||
> **<sup>Syntax</sup>** | ||
> _MatchExpression_ : | ||
> `match` [_Expression_]<sub>_except struct expression_</sub> `{` | ||
> [_InnerAttribute_]<sup>\*</sup> | ||
> _MatchArms_<sup>?</sup> | ||
> `}` | ||
> | ||
> _MatchArms_ : | ||
> ( _MatchArm_ `=>` | ||
> ( [_BlockExpression_] `,`<sup>?</sup> | ||
> | [_Expression_] `,` ) | ||
> )<sup>\*</sup> | ||
> _MatchArm_ `=>` ( [_BlockExpression_] | [_Expression_] ) `,`<sup>?</sup> | ||
> | ||
> _MatchArm_ : | ||
> [_OuterAttribute_]<sup>\*</sup> _MatchArmPatterns_ _MatchArmGuard_<sup>?</sup> | ||
> | ||
> _MatchArmPatterns_ : | ||
> `|`<sup>?</sup> _Pattern_ ( `|` _Pattern_ )<sup>*</sup> | ||
> | ||
> _MatchArmGuard_ : | ||
> `if` [_Expression_] | ||
> )<sup>\*</sup> | ||
> _MatchArm_ `=>` ( [_BlockExpression_] | [_Expression_] ) `,`<sup>?</sup> | ||
> | ||
> _MatchArm_ : | ||
> [_OuterAttribute_]<sup>\*</sup> _MatchArmPatterns_ _MatchArmGuard_<sup>?</sup> | ||
> | ||
> _MatchArmPatterns_ : | ||
> `|`<sup>?</sup> [_Pattern_] ( `|` [_Pattern_] )<sup>*</sup> | ||
> | ||
> _MatchArmGuard_ : | ||
> `if` [_Expression_] | ||
|
||
A `match` expression branches on a *pattern*. The exact form of matching that | ||
occurs depends on the pattern. Patterns consist of some combination of | ||
literals, destructured arrays or enum constructors, structs and tuples, | ||
variable binding specifications, wildcards (`..`), and placeholders (`_`). A | ||
`match` expression has a *head expression*, which is the value to compare to | ||
the patterns. The type of the patterns must equal the type of the head | ||
expression. | ||
occurs depends on the pattern. See [Patterns] for more details. A `match` | ||
expression has a *head expression*, which is the value to compare to the | ||
patterns. The type of the patterns must equal the type of the head expression. | ||
|
||
A `match` behaves differently depending on whether or not the head expression | ||
is a [place expression or value expression][place expression]. | ||
|
@@ -65,61 +62,9 @@ match x { | |
Patterns that bind variables default to binding to a copy or move of the | ||
matched value (depending on the matched value's type). This can be changed to | ||
bind to a reference by using the `ref` keyword, or to a mutable reference using | ||
`ref mut`. | ||
`ref mut`. See [Identifier Patterns]. | ||
|
||
Patterns can be used to *destructure* structs, enums, and tuples. Destructuring | ||
breaks a value up into its component pieces. The syntax used is the same as | ||
when creating such values. When destructing a data structure with named (but | ||
not numbered) fields, it is allowed to write `fieldname` as a shorthand for | ||
`fieldname: fieldname`. In a pattern whose head expression has a `struct`, | ||
`enum` or `tupl` type, a placeholder (`_`) stands for a *single* data field, | ||
whereas a wildcard `..` stands for *all* the fields of a particular variant. | ||
|
||
```rust | ||
# enum Message { | ||
# Quit, | ||
# WriteString(String), | ||
# Move { x: i32, y: i32 }, | ||
# ChangeColor(u8, u8, u8), | ||
# } | ||
# let message = Message::Quit; | ||
match message { | ||
Message::Quit => println!("Quit"), | ||
Message::WriteString(write) => println!("{}", &write), | ||
Message::Move{ x, y: 0 } => println!("move {} horizontally", x), | ||
Message::Move{ .. } => println!("other move"), | ||
Message::ChangeColor { 0: red, 1: green, 2: _ } => { | ||
println!("color change, red: {}, green: {}", red, green); | ||
} | ||
}; | ||
``` | ||
|
||
Patterns can also dereference pointers by using the `&`, `&mut` and `box` | ||
symbols, as appropriate. For example, these two matches on `x: &i32` are | ||
equivalent: | ||
|
||
```rust | ||
# let x = &3; | ||
let y = match *x { 0 => "zero", _ => "some" }; | ||
let z = match x { &0 => "zero", _ => "some" }; | ||
|
||
assert_eq!(y, z); | ||
``` | ||
|
||
Subpatterns can also be bound to variables by the use of the syntax `variable @ | ||
subpattern`. For example: | ||
|
||
```rust | ||
let x = 1; | ||
|
||
match x { | ||
e @ 1 ... 5 => println!("got a range element {}", e), | ||
_ => println!("anything"), | ||
} | ||
``` | ||
|
||
Multiple match patterns may be joined with the `|` operator. An inclusive range | ||
of values may be specified with `..=`. For example: | ||
Multiple match patterns may be joined with the `|` operator: | ||
|
||
```rust | ||
# let x = 9; | ||
|
@@ -132,34 +77,13 @@ let message = match x { | |
assert_eq!(message, "a few"); | ||
``` | ||
|
||
Other forms of [range] \(`..` for an exclusive range, or any range with one or | ||
both endpoints left unspecified) are not supported in matches. The | ||
syntax `...` is also accepted for inclusive ranges in patterns only, for | ||
backwards compatibility. | ||
|
||
Range patterns only work [`char`] and [numeric types]. A range pattern may not | ||
be a sub-range of another range pattern inside the same `match`. | ||
Please notice that the `2..=9` is a [Range Pattern], not a [Range Expression] | ||
and, thus, only those types of ranges supported by range patterns can be used | ||
in match arms. | ||
|
||
Slice patterns can match both arrays of fixed size and slices of dynamic size. | ||
```rust | ||
// Fixed size | ||
let arr = [1, 2, 3]; | ||
match arr { | ||
[1, _, _] => "starts with one", | ||
[a, b, c] => "starts with something else", | ||
}; | ||
``` | ||
```rust | ||
// Dynamic size | ||
let v = vec![1, 2, 3]; | ||
match v[..] { | ||
[a, b] => { /* this arm will not apply because the length doesn't match */ } | ||
[a, b, c] => { /* this arm will apply */ } | ||
_ => { /* this wildcard is required, since we don't know length statically */ } | ||
} | ||
``` | ||
A range pattern may not be a sub-range of another range pattern inside the same `match`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't seem to be true; https://play.rust-lang.org/?gist=49813df7725fc36a71959a136841ce14&version=nightly shows only a warning. |
||
|
||
Finally, match patterns can accept *pattern guards* to further refine the | ||
Match patterns can accept _match guards_ to further refine the | ||
criteria for matching a case. Pattern guards appear after the pattern and | ||
consist of a bool-typed expression following the `if` keyword. A pattern guard | ||
may refer to the variables bound within the pattern they follow. | ||
|
@@ -179,8 +103,14 @@ let message = match maybe_digit { | |
[_BlockExpression_]: expressions/block-expr.html#block-expressions | ||
[place expression]: expressions.html#place-expressions-and-value-expressions | ||
[value expression]: expressions.html#place-expressions-and-value-expressions | ||
[`char`]: types.html#textual-types | ||
[numeric types]: types.html#numeric-types | ||
[_InnerAttribute_]: attributes.html | ||
[_OuterAttribute_]: attributes.html | ||
[range]: expressions/range-expr.html | ||
[Range Expression]: expressions/range-expr.html | ||
|
||
[_Pattern_]: patterns.html | ||
[Patterns]: patterns.html | ||
[Identifier Patterns]: patterns.html#identifier-patterns | ||
[Struct Patterns]: patterns.html#struct-patterns | ||
[Tuple Struct Patterns]: patterns.html#tuplestruct-patterns | ||
[Tuple Patterns]: patterns.html#tuple-patterns | ||
[Range Pattern]: patterns.html#range-patterns |
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.
@Havvy should this be under Statements and expressions?