Skip to content

Commit c0343a7

Browse files
committed
Add rest patterns.
1 parent b0bc669 commit c0343a7

File tree

1 file changed

+70
-5
lines changed

1 file changed

+70
-5
lines changed

src/patterns.md

+70-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
>       [_LiteralPattern_]\
66
>    | [_IdentifierPattern_]\
77
>    | [_WildcardPattern_]\
8+
>    | [_RestPattern_]\
89
>    | [_RangePattern_]\
910
>    | [_ReferencePattern_]\
1011
>    | [_StructPattern_]\
@@ -317,6 +318,59 @@ if let Some(_) = x {}
317318

318319
The wildcard pattern is always irrefutable.
319320

321+
## Rest patterns
322+
323+
> **<sup>Syntax</sup>**\
324+
> _RestPattern_ :\
325+
> &nbsp;&nbsp; `..`
326+
327+
The _rest pattern_ (the `..` token) acts as a variable-length pattern which
328+
matches zero or more elements that haven't been matched already before and
329+
after. It may only be used in [tuple](#tuple-patterns), [tuple
330+
struct](#tuple-struct-patterns), and [slice](#slice-patterns) patterns, and
331+
may only appear once as one of the elements in those patterns. It is also
332+
allowed in an [identifier pattern](#identifier-patterns) for [slice
333+
patterns](#slice-patterns) only.
334+
335+
The rest pattern is always irrefutable.
336+
337+
Examples:
338+
339+
```rust
340+
# let words = vec!["a", "b", "c"];
341+
# let slice = &words[..];
342+
match slice {
343+
[] => println!("slice is empty"),
344+
[one] => println!("single element {}", one),
345+
[head, tail @ ..] => println!("head={} tail={:?}", head, tail),
346+
}
347+
348+
match slice {
349+
// Ignore everything but the last element, which must be "!".
350+
[.., "!"] => println!("!!!"),
351+
352+
// `start` is a slice of everything except the last element, which must be "z".
353+
[start @ .., "z"] => println!("starts with: {:?}", start),
354+
355+
// `end` is a slice of everything but the first element, which must be "a".
356+
["a", end @ ..] => println!("ends with: {:?}", end),
357+
358+
rest => println!("{:?}", rest),
359+
}
360+
361+
if let [.., penultimate, _] = slice {
362+
println!("next to last is {}", penultimate);
363+
}
364+
365+
# let tuple = (1, 2, 3, 4, 5);
366+
// Rest patterns may also be used in tuple and tuple struct patterns.
367+
match tuple {
368+
(1, .., y, z) => println!("y={} z={}", y, z),
369+
(.., 5) => println!("tail must be 5"),
370+
(..) => println!("matches everything else"),
371+
}
372+
```
373+
320374
## Range patterns
321375

322376
> **<sup>Syntax</sup>**\
@@ -559,8 +613,7 @@ A struct pattern is refutable when one of its subpatterns is refutable.
559613
> &nbsp;&nbsp; [_PathInExpression_] `(` _TupleStructItems_<sup>?</sup> `)`
560614
>
561615
> _TupleStructItems_ :\
562-
> &nbsp;&nbsp; &nbsp;&nbsp; [_Pattern_]&nbsp;( `,` [_Pattern_] )<sup>\*</sup> `,`<sup>?</sup>\
563-
> &nbsp;&nbsp; | ([_Pattern_] `,`)<sup>\*</sup> `..` (`,` [_Pattern_])<sup>*</sup> `,`<sup>?</sup>
616+
> &nbsp;&nbsp; [_Pattern_]&nbsp;( `,` [_Pattern_] )<sup>\*</sup> `,`<sup>?</sup>
564617
565618
Tuple struct patterns match tuple struct and enum values that match all criteria defined
566619
by its subpatterns. They are also used to [destructure](#destructuring) a tuple struct or
@@ -576,12 +629,15 @@ A tuple struct pattern is refutable when one of its subpatterns is refutable.
576629
>
577630
> _TuplePatternItems_ :\
578631
> &nbsp;&nbsp; &nbsp;&nbsp; [_Pattern_] `,`\
579-
> &nbsp;&nbsp; | [_Pattern_]&nbsp;(`,` [_Pattern_])<sup>+</sup> `,`<sup>?</sup>\
580-
> &nbsp;&nbsp; | ([_Pattern_] `,`)<sup>\*</sup> `..` (`,` [_Pattern_])<sup>*</sup> `,`<sup>?</sup>
632+
> &nbsp;&nbsp; | [_RestPattern_]\
633+
> &nbsp;&nbsp; | [_Pattern_]&nbsp;(`,` [_Pattern_])<sup>+</sup> `,`<sup>?</sup>
581634
582635
Tuple patterns match tuple values that match all criteria defined by its subpatterns.
583636
They are also used to [destructure](#destructuring) a tuple.
584637

638+
The form `(..)` with a single [_RestPattern_] is a special form that does not
639+
require a comma, and matches a tuple of any size.
640+
585641
This pattern is refutable when one of its subpatterns is refutable.
586642

587643
## Grouped patterns
@@ -607,7 +663,10 @@ match int_reference {
607663

608664
> **<sup>Syntax</sup>**\
609665
> _SlicePattern_ :\
610-
> &nbsp;&nbsp; `[` [_Pattern_] \(`,` [_Pattern_])<sup>\*</sup> `,`<sup>?</sup> `]`
666+
> &nbsp;&nbsp; `[` _SlicePatternItems_<sup>?</sup> `]`
667+
>
668+
> _SlicePatternItems_ :\
669+
> &nbsp;&nbsp; [_Pattern_] \(`,` [_Pattern_])<sup>\*</sup> `,`<sup>?</sup>
611670
612671
Slice patterns can match both arrays of fixed size and slices of dynamic size.
613672
```rust
@@ -628,6 +687,11 @@ match v[..] {
628687
};
629688
```
630689

690+
Slice patterns are irrefutable when matching an array as long as each element
691+
is irrefutable. When matching a slice, it is irrefutable only in the form with
692+
a single `..` [rest pattern](#rest-patterns) or [identifier
693+
pattern](#identifier-patterns) with the `..` rest pattern as a subpattern.
694+
631695
## Path patterns
632696

633697
> **<sup>Syntax</sup>**\
@@ -664,6 +728,7 @@ refer to refutable constants or enum variants for enums with multiple variants.
664728
[_QualifiedPathInExpression_]: paths.md#qualified-paths
665729
[_RangePattern_]: #range-patterns
666730
[_ReferencePattern_]: #reference-patterns
731+
[_RestPattern_]: #rest-patterns
667732
[_SlicePattern_]: #slice-patterns
668733
[_StructPattern_]: #struct-patterns
669734
[_TuplePattern_]: #tuple-patterns

0 commit comments

Comments
 (0)