From b72ff837086cf05fe8aff7c2ce5c56225fdc6a3b Mon Sep 17 00:00:00 2001 From: Martijn Hoekstra Date: Mon, 30 Nov 2020 15:51:32 +0100 Subject: [PATCH] Spec for name based and irrefutable patterns --- spec/08-pattern-matching.md | 92 ++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 21 deletions(-) diff --git a/spec/08-pattern-matching.md b/spec/08-pattern-matching.md index 4dee789118a5..e9edc0011dcd 100644 --- a/spec/08-pattern-matching.md +++ b/spec/08-pattern-matching.md @@ -240,33 +240,40 @@ the pattern. An extractor pattern cannot match the value `null`. The implementation ensures that the `unapply`/`unapplySeq` method is not applied to `null`. +The type $O$ is said to be an _extractor type_ for some type $T$ if it has a +method `get` with return type `$T$`, and a method `isEmpty` with a return type +that conforms to `Boolean`. `Option[$T$]` is an extractor type for type `$T$`. + An `unapply` method in an object $x$ _matches_ the pattern $x(p_1 , \ldots , p_n)$ if it has a single parameter (and, optionally, an implicit parameter list) and one of the following applies: -* $n=0$ and `unapply`'s result type is `Boolean`. In this case - the extractor pattern matches all values $v$ for which - `$x$.unapply($v$)` yields `true`. -* $n=1$ and `unapply`'s result type is `Option[$T$]`, for some - type $T$. In this case, the (only) argument pattern $p_1$ is typed in - turn with expected type $T$. The extractor pattern matches then all - values $v$ for which `$x$.unapply($v$)` yields a value of form - `Some($v_1$)`, and $p_1$ matches $v_1$. -* $n>1$ and `unapply`'s result type is - `Option[($T_1 , \ldots , T_n$)]`, for some - types $T_1 , \ldots , T_n$. In this case, the argument patterns $p_1 - , \ldots , p_n$ are typed in turn with expected types $T_1 , \ldots , - T_n$. The extractor pattern matches then all values $v$ for which - `$x$.unapply($v$)` yields a value of form - `Some(($v_1 , \ldots , v_n$))`, and each pattern - $p_i$ matches the corresponding value $v_i$. +* $n=0$ and `unapply`'s result type conforms to `Boolean`. In this case the + extractor pattern matches all values $v$ for which `$x$.unapply($v$)` + yields `true`. +* $n=1$ and `unapply`'s result type is and extractor type for some type `$T$`. + In this case, the (only) argument pattern $p_1$ is typed in turn with expected + type $T$. The extractor pattern matches then all values $v$ for which + `$x$.unapply($v$)` yields a value `$u$` for which `$u$.isEmpty` yields + `false`, `$u$.get` yields a value `$v_1$`, and `$p$` matches value `$v_1$`. +* $n>1$ and `unapply`'s result type is an extractor type for some type `$T$` + with members `$\_1 , \ldots , \_n$` returning some types $T_1, \ldots, T_n$. + In this case, the argument patterns $p_1, \ldots , p_n$ are typed in turn with + expected types $T_1 , \ldots , T_n$. The extractor pattern matches then all + values $v$ for which `$x$.unapply($v$)` yields a value `$u$` for which + `$u$.isEmpty` yields `false`, `$u$.get` yields some value `$t$` and each + pattern $p_i$ matches the corresponding value $t.\\_i$ from + `$t.\_1 , \ldots , t.\_n$`. An `unapplySeq` method in an object $x$ matches the pattern $x(q_1 , \ldots , q_m, p_1 , \ldots , p_n)$ if it takes exactly one argument -and its result type is of the form `Option[($T_1 , \ldots , T_m$, Seq[S])]` (if `m = 0`, the type `Option[Seq[S]]` is also accepted). +and its result type is an extractor type for the type +`($T_1 , \ldots , T_m$, Seq[S])`. (if `m = 0`, an extractor type for `Seq[S]` +is also accepted). + This case is further discussed [below](#pattern-sequences). -###### Example +###### Example 1 If we define an extractor object `Pair`: @@ -288,6 +295,37 @@ val y = x match { } ``` +###### Example 2 + +If we define a class `NameBased` + +```scala +class NameBased[A, B](a: A, b: B) { + def isEmpty = false + def get = this + def _1 = a + def _2 = b +} +``` + +Then `NameBased` is an extractor type for `NameBased` itself, since it has a +member `isEmpty` returning a value of type Boolean, and it has a member `get` +returning a value of type `NameBased`. + +Since it also has members `_1` and `_2`, it can be used in an extractor pattern +with n = 2 as follows: + +```scala +object Extractor { + def unapply(x: Any) = new NameBased(1, "two") +} + +"anything" match { + case Extractor(a, b) => println(s"\$a, \$b") //prints "1, two" +} +``` + + ### Pattern Sequences ```ebnf @@ -295,9 +333,15 @@ SimplePattern ::= StableId ‘(’ [Patterns ‘,’] [varid ‘@’] ‘_’ ``` A _pattern sequence_ $p_1 , \ldots , p_n$ appears in two contexts. -First, in a constructor pattern $c(q_1 , \ldots , q_m, p_1 , \ldots , p_n)$, where $c$ is a case class which has $m+1$ primary constructor parameters, ending in a [repeated parameter](04-basic-declarations-and-definitions.html#repeated-parameters) of type `S*`. -Second, in an extractor pattern $x(q_1 , \ldots , q_m, p_1 , \ldots , p_n)$ if the extractor object $x$ does not have an `unapply` method, -but it does define an `unapplySeq` method with a result type conforming to `Option[(T_1, ... , T_m, Seq[S])]` (if `m = 0`, the type `Option[Seq[S]]` is also accepted). The expected type for the patterns $p_i$ is $S$. +First, in a constructor pattern $c(q_1 , \ldots , q_m, p_1 , \ldots , p_n)$, +where $c$ is a case class which has $m+1$ primary constructor parameters, +ending in a [repeated parameter](04-basic-declarations-and-definitions.html#repeated-parameters) +of type `S*`. +Second, in an extractor pattern $x(q_1 , \ldots , q_m, p_1 , \ldots , p_n)$ if +the extractor object $x$ does not have an `unapply` method, but it does define +an `unapplySeq` method with a result type an extractor type for type +`(T_1, ... , T_m, Seq[S])` (if `m = 0`, an extractor type for type `Seq[S]` +is also accepted). The expected type for the patterns $p_i$ is $S$. The last pattern in a pattern sequence may be a _sequence wildcard_ `_*`. Each element pattern $p_i$ is type-checked with @@ -366,6 +410,12 @@ A pattern $p$ is _irrefutable_ for a type $T$, if one of the following applies: is an instance of class $c$, the [primary constructor](05-classes-and-objects.html#class-definitions) of type $T$ has argument types $T_1 , \ldots , T_n$, and each $p_i$ is irrefutable for $T_i$. +1. $p$ is an extractor pattern for which the extractor type is `Some[$T$]` for + some type `$T$` +1. $p$ is an extractor pattern for which the extractor types `isEmpty` method + is the singleton type `false` +1. $p$ is an extractor pattern for which the return type is the singleton type + `true` ## Type Patterns