@@ -7,9 +7,74 @@ Dotty implementation of pattern matching was greatly simplified compared to scal
7
7
8
8
Dotty supports a superset of scalac's [ extractors] ( https://www.scala-lang.org/files/archive/spec/2.13/08-pattern-matching.html#extractor-patterns ) .
9
9
10
- ## Boolean Pattern
10
+ ## Extractors
11
11
12
- - Extractor defines ` def unapply(x: T): Boolean `
12
+ Extractors are objects that expose a method ` unapply ` or ` unapplySeq ` :
13
+
14
+ ``` Scala
15
+ def unapply [A ](x : T )(implicit x : B ): U
16
+ def unapplySeq [A ](x : T )(implicit x : B ): U
17
+ ```
18
+
19
+ Extractors expose the method ` unapply ` are called fix-arity extractors, which
20
+ work with patterns of fixed arity. Extractors expose the method ` unapplySeq ` are
21
+ called variadic extractors, which enables variadic patterns.
22
+
23
+ ### Fixed-Arity Extractors
24
+
25
+ Fixed-arity extractors expose the following signature:
26
+
27
+ ``` Scala
28
+ def unapply [A ](x : T )(implicit x : B ): U
29
+ ```
30
+
31
+ The type ` U ` conforms to one of the following matches:
32
+
33
+ - Boolean match
34
+ - Product match
35
+
36
+ Or ` U ` conforms to the type ` R ` :
37
+
38
+ ``` Scala
39
+ type R = {
40
+ def isEmpty : Boolean
41
+ def get : S
42
+ }
43
+ ```
44
+
45
+ and ` S ` conforms to one of the following matches:
46
+
47
+ - Single match
48
+ - Name-based match
49
+
50
+
51
+ ### Variadic Extractors
52
+
53
+ Variadic extractors expose the following signature:
54
+
55
+ ``` Scala
56
+ def unapplySeq [A ](x : T )(implicit x : B ): U
57
+ ```
58
+
59
+ The type ` U ` conforms to one of the following matches:
60
+
61
+ - Sequence match
62
+ - Product-sequence match
63
+
64
+ Or ` U ` conforms to the type ` R ` :
65
+
66
+ ``` Scala
67
+ type R = {
68
+ def isEmpty : Boolean
69
+ def get : S
70
+ }
71
+ ```
72
+
73
+ and ` S ` conforms to one of the two matches above.
74
+
75
+ ## Boolean Match
76
+
77
+ - ` U =:= Boolean `
13
78
- Pattern-matching on exactly ` 0 ` patterns
14
79
15
80
For example:
@@ -28,10 +93,8 @@ object Even {
28
93
// even has an even number of characters
29
94
```
30
95
96
+ ## Product Match
31
97
32
- ## Product Pattern
33
-
34
- - Extractor defines ` def unapply(x: T): U `
35
98
- ` U <: Product `
36
99
- ` N > 0 ` is the maximum number of consecutive (parameterless ` def ` or ` val ` ) ` _1: P1 ` ... ` _N: PN ` members in ` U `
37
100
- Pattern-matching on exactly ` N ` patterns with types ` P1, P2, ..., PN `
@@ -62,12 +125,53 @@ object FirstChars {
62
125
// First: H; Second: i
63
126
```
64
127
128
+ ## Single Match
129
+
130
+ - If there is exactly ` 1 ` pattern, pattern-matching on ` 1 ` pattern with type ` U `
131
+
132
+ <!-- To be kept in sync with tests/new/patmat-spec.scala -->
133
+
134
+ ``` scala
135
+ class Nat (val x : Int ) {
136
+ def get : Int = x
137
+ def isEmpty = x < 0
138
+ }
139
+
140
+ object Nat {
141
+ def unapply (x : Int ): Nat = new Nat (x)
142
+ }
143
+
144
+ 5 match {
145
+ case Nat (n) => println(s " $n is a natural number " )
146
+ case _ => ()
147
+ }
148
+ // 5 is a natural number
149
+ ```
150
+
151
+ ## Name-based Match
152
+
153
+ - ` N > 1 ` is the maximum number of consecutive (parameterless ` def ` or ` val ` ) ` _1: P1 ... _N: PN ` members in ` U `
154
+ - Pattern-matching on exactly ` N ` patterns with types ` P1, P2, ..., PN `
155
+
156
+ ``` Scala
157
+ object ProdEmpty {
158
+ def _1 : Int = ???
159
+ def _2 : String = ???
160
+ def isEmpty = true
161
+ def unapply (s : String ): this .type = this
162
+ def get = this
163
+ }
164
+
165
+ " " match {
166
+ case ProdEmpty (_, _) => ???
167
+ case _ => ()
168
+ }
169
+ ```
170
+
65
171
66
- ## Name-based Seq Pattern
172
+ ## Seq Match
67
173
68
- - Extractor defines ` def unapplySeq(x: T): U `
69
- - ` U ` has (parameterless ` def ` or ` val ` ) members ` isEmpty: Boolean ` and ` get: S `
70
- - ` S ` conforms to ` X ` , ` T2 ` and ` T3 ` conform to ` T1 `
174
+ - ` U <: X ` , ` T2 ` and ` T3 ` conform to ` T1 `
71
175
72
176
``` Scala
73
177
type X = {
@@ -97,32 +201,22 @@ object CharList {
97
201
// e,x,a,m
98
202
```
99
203
204
+ ## Product-Seq Match
100
205
101
- ## Name-based Pattern
102
-
103
- - Extractor defines ` def unapply(x: T): U `
104
- - ` U ` has (parameterless ` def ` or ` val ` ) members ` isEmpty: Boolean ` and ` get: S `
105
- - If there is exactly ` 1 ` pattern, pattern-matching on ` 1 ` pattern with type ` S `
106
- - Otherwise ` N > 0 ` is the maximum number of consecutive (parameterless ` def ` or ` val ` ) ` _1: P1 ` ... ` _N: PN ` members in ` U `
107
- - Pattern-matching on exactly ` N ` patterns with types ` P1, P2, ..., PN `
108
-
109
- <!-- To be kept in sync with tests/new/patmat-spec.scala -->
110
-
111
- ``` scala
112
- class Nat (val x : Int ) {
113
- def get : Int = x
114
- def isEmpty = x < 0
115
- }
206
+ - ` U <: Product `
207
+ - ` N > 0 ` is the maximum number of consecutive (parameterless ` def ` or ` val ` ) ` _1: P1 ` ... ` _N: PN ` members in ` U `
208
+ - ` PN ` conforms to the signature ` X ` defined in Seq Pattern
209
+ - Pattern-matching on exactly ` >= N ` patterns, the first ` N - 1 ` patterns have types ` P1, P2, ... P(N-1) ` ,
210
+ the type of the remaining patterns are determined as in Seq Pattern.
116
211
117
- object Nat {
118
- def unapply (x : Int ): Nat = new Nat (x)
212
+ ``` Scala
213
+ class Foo (val name : String , val children : Int * )
214
+ object Foo {
215
+ def unapplySeq (f : Foo ): Option [(String , Seq [Int ])] = Some ((f.name, f.children))
119
216
}
120
217
121
- 5 match {
122
- case Nat (n) => println( s " $n is a natural number " )
123
- case _ => ()
218
+ def foo ( f : Foo ) = f match {
219
+ case Foo (name, ns : _* ) =>
220
+ case Foo (name, x, y, ns : _* ) =>
124
221
}
125
- // 5 is a natural number
126
- ```
127
-
128
- In case of ambiguities, * Product Pattern* is preferred over * Name Based Pattern* . This document reflects the state of pattern matching as currently implemented in Dotty. There are plans for further simplification, in particular to factor out * Product Pattern* and * Name Based Pattern* into a single type of extractor.
222
+ ```
0 commit comments