Skip to content

Commit

Permalink
Spec for name based and irrefutable patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnhoekstra committed Dec 7, 2020
1 parent d45a673 commit caf5eb1
Showing 1 changed file with 71 additions and 21 deletions.
92 changes: 71 additions & 21 deletions spec/08-pattern-matching.md
Expand Up @@ -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 is `Boolean`, or one of the literal types
`true` or `false`. 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`:

Expand All @@ -288,16 +295,53 @@ 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
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
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit caf5eb1

Please sign in to comment.