Skip to content

Patterns chapter #419

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

Merged
merged 10 commits into from
Sep 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
- [Match expressions](expressions/match-expr.md)
- [Return expressions](expressions/return-expr.md)

- [Patterns](patterns.md)

- [Type system](type-system.md)
- [Types](types.md)
- [Dynamically Sized Types](dynamically-sized-types.md)
Expand Down
3 changes: 2 additions & 1 deletion src/expressions/closure-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

A _closure expression_ defines a closure and denotes it as a value, in a single
expression. A closure expression is a pipe-symbol-delimited (`|`) list of
patterns followed by an expression. Type annotations may optionally be added
irrefutable [patterns] followed by an expression. Type annotations may optionally be added
for the type of the parameters or for the return type. If there is a return
type, the expression used for the body of the closure must be a normal
[block]. A closure expression also may begin with the
Expand Down Expand Up @@ -63,6 +63,7 @@ ten_times(move |j| println!("{}, {}", word, j));

[block]: expressions/block-expr.html
[function definitions]: items/functions.html
[patterns]: patterns.html

[_Expression_]: expressions.html
[_BlockExpression_]: expressions/block-expr.html
Expand Down
3 changes: 2 additions & 1 deletion src/expressions/if-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ assert_eq!(y, "Bigger");

> **<sup>Syntax</sup>**\
> _IfLetExpression_ :\
> &nbsp;&nbsp; `if` `let` _Pattern_ `=` [_Expression_]<sub>_except struct expression_</sub>
> &nbsp;&nbsp; `if` `let` [_Pattern_] `=` [_Expression_]<sub>_except struct expression_</sub>
> [_BlockExpression_]\
> &nbsp;&nbsp; (`else` (
> [_BlockExpression_]
Expand Down Expand Up @@ -113,3 +113,4 @@ match EXPR {

[_Expression_]: expressions.html
[_BlockExpression_]: expressions/block-expr.html
[_Pattern_]: patterns.html
5 changes: 3 additions & 2 deletions src/expressions/loop-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ while i < 10 {

> **<sup>Syntax</sup>**\
> [_PredicatePatternLoopExpression_] :\
> &nbsp;&nbsp; `while` `let` _Pattern_ `=` [_Expression_]<sub>except struct expression</sub>
> &nbsp;&nbsp; `while` `let` [_Pattern_] `=` [_Expression_]<sub>except struct expression</sub>
> [_BlockExpression_]

A `while let` loop is semantically similar to a `while` loop but in place of a
Expand Down Expand Up @@ -109,7 +109,7 @@ is equivalent to

> **<sup>Syntax</sup>**\
> _IteratorLoopExpression_ :\
> &nbsp;&nbsp; `for` _Pattern_ `in` [_Expression_]<sub>except struct expression</sub>
> &nbsp;&nbsp; `for` [_Pattern_] `in` [_Expression_]<sub>except struct expression</sub>
> [_BlockExpression_]

A `for` expression is a syntactic construct for looping over elements provided
Expand Down Expand Up @@ -271,5 +271,6 @@ expression `()`.

[_Expression_]: expressions.html
[_BlockExpression_]: expressions/block-expr.html
[_Pattern_]: patterns.html

[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels
116 changes: 21 additions & 95 deletions src/expressions/match-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,15 @@
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup> _MatchArmPatterns_ _MatchArmGuard_<sup>?</sup>
>
> _MatchArmPatterns_ :\
> &nbsp;&nbsp; `|`<sup>?</sup> _Pattern_ ( `|` _Pattern_ )<sup>\*</sup>
> &nbsp;&nbsp; `|`<sup>?</sup> [_Pattern_] ( `|` [_Pattern_] )<sup>\*</sup>
>
> _MatchArmGuard_ :\
> &nbsp;&nbsp; `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]. A `match`
expression has a *head expression*, which is the value to compare to the
patterns. The head expression and the patterns must have the same type.

A `match` behaves differently depending on whether or not the head expression
is a [place expression or value expression][place expression].
Expand Down Expand Up @@ -62,65 +59,10 @@ 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`.
Variables bound within the pattern are scoped to the match guard and the arm's
expression. The [binding mode] (move, copy, or reference) depends on the pattern.

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 int_reference = &3;

let a = match *int_reference { 0 => "zero", _ => "some" };
let b = match int_reference { &0 => "zero", _ => "some" };

assert_eq!(a, b);
```

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;
Expand All @@ -133,34 +75,11 @@ let message = match x {
assert_eq!(message, "a few");
```

Other forms of [range] \(e.g `..` 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 with [`char`] and [numeric types]. A range pattern may
not be a sub-range of another range pattern inside the same `match`.

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 */ }
}
```
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.

Finally, match arms can accept *pattern guards* to further refine the
Match arms 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.
Expand Down Expand Up @@ -205,10 +124,17 @@ meaning on match arms are [`cfg`], `cold`, and the [lint check attributes].
[_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
[`cfg`]: conditional-compilation.html
[lint check attributes]: attributes.html#lint-check-attributes
[range]: expressions/range-expr.html
[Range Expression]: expressions/range-expr.html

[_Pattern_]: patterns.html
[pattern]: 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
[binding mode]: patterns.html#binding-modes
7 changes: 4 additions & 3 deletions src/items/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fn answer_to_life_the_universe_and_everything() -> i32 {
}
```

As with `let` bindings, function arguments are irrefutable patterns, so any
As with `let` bindings, function arguments are irrefutable [patterns], so any
pattern that is valid in a let binding is also valid as an argument:

```rust
Expand Down Expand Up @@ -120,7 +120,7 @@ implemented by executing an illegal instruction.
[Outer attributes][attributes] are allowed on functions. [Inner
attributes][attributes] are allowed directly after the `{` inside its [block].

This example shows an inner attribute on a function. The function will only be
This example shows an inner attribute on a function. The function will only be
available while running tests.

```
Expand Down Expand Up @@ -153,4 +153,5 @@ attributes].
[the optimization hint attributes]: attributes.html#optimization-hints
[`deprecated`]: attributes.html#deprecation
[`doc`]: attributes.html#documentation
[`must_use`]: attributes.html#must_use
[`must_use`]: attributes.html#must_use
[patterns]: patterns.html
2 changes: 1 addition & 1 deletion src/macros-by-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ syntax named by _designator_. Valid designators are:
[item]: items.html
[block]: expressions/block-expr.html
[statement]: statements.html
[pattern]: expressions/match-expr.html
[pattern]: patterns.html
[expression]: expressions.html
[type]: types.html
[identifier]: identifiers.html
Expand Down
Loading