@@ -7,9 +7,74 @@ Dotty implementation of pattern matching was greatly simplified compared to scal
77
88Dotty supports a superset of scalac's [ extractors] ( https://www.scala-lang.org/files/archive/spec/2.13/08-pattern-matching.html#extractor-patterns ) .
99
10- ## Boolean Pattern
10+ ## Extractors
1111
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 `
1378- Pattern-matching on exactly ` 0 ` patterns
1479
1580For example:
@@ -28,10 +93,8 @@ object Even {
2893// even has an even number of characters
2994```
3095
96+ ## Product Match
3197
32- ## Product Pattern
33-
34- - Extractor defines ` def unapply(x: T): U `
3598- ` U <: Product `
3699- ` N > 0 ` is the maximum number of consecutive (parameterless ` def ` or ` val ` ) ` _1: P1 ` ... ` _N: PN ` members in ` U `
37100- Pattern-matching on exactly ` N ` patterns with types ` P1, P2, ..., PN `
@@ -62,12 +125,53 @@ object FirstChars {
62125// First: H; Second: i
63126```
64127
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+
65171
66- ## Name-based Seq Pattern
172+ ## Seq Match
67173
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 `
71175
72176``` Scala
73177type X = {
@@ -97,32 +201,22 @@ object CharList {
97201// e,x,a,m
98202```
99203
204+ ## Product-Seq Match
100205
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.
116211
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))
119216}
120217
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 : _* ) =>
124221}
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