-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Name-based pattern matching rules #1805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This implements the rules laid down in scala#1805.
These rules don't make |
I think you mean case classes |
@Blaisorblade |
Product pattern use to: - have a `<: Product` requirement - compute the arity of a pattern by looking at `N` in a `ProductN` superclass. This commit changes `<: Product`, instead we look for a `_1` member. The arity is determined by inspecting `_1` to `_N` members instead. --- Here another attempt to formalize Dotty's pattern-matching (base on scala#1805). This covers the *Extractor Patterns* [section of the spec](https://www.scala-lang.org/files/archive/spec/2.12/08-pattern-matching.html#extractor-patterns). Dotty support 4 different extractor patterns: Boolean Pattern, Product Pattern, Seq Pattern and Name Based Pattern. Boolean Pattern - Extractor defines `def unapply(x: T): Boolean` - Pattern-matching on exactly `0` patterns Product Pattern - Extractor defines `def unapply(x: T): U` - `N > 0` is the maximum number of consecutive (parameterless `def` or `val`) `_1: P1` ... `_N: PN` members in `U` - Pattern-matching on exactly `N` patterns with types `P1, P2, ..., PN` Seq Pattern - Extractor defines `def unapplySeq(x: T): U` - `U` has (parameterless `def` or `val`) members `isEmpty: Boolean` and `get: S` - `S <: Seq[V]` - Pattern-matching on any number of pattern with types `V, V, ..., V` Name Based Pattern - Extractor defines `def unapply(x: T): U` - `U` has (parameterless `def` or `val`) members `isEmpty: Boolean` and `get: S` - If there is exactly `1` pattern, pattern-matching on `1` pattern with type `S` - Otherwise fallback to Product Pattern on type `U` In case of ambiguities, *Product Pattern* is preferred over *Name Based Pattern*.
This is an attempt to come up with a sane set of rules for name-based pattern matching. To recall: In dotty, name-based is all we have, there is no special treatment of type classes anymore.
The purpose of the rules is, given a pattern
P(P1, .., Pn)
, to produce the expected typesPT1,..., PTn
against which the argument patternsP1, .., Pn
will be matched. LetX
be the expected type of the whole pattern match.If the companion object
P
contains a memberdef unapply(x: T): U
such thatX
conforms toT
thenIf
U
is a subtype of a product typeProduct{n}[T1, ... Tn]
with arityn
thenPTi = Ti
, fori = 1,..,n
.If
U
has parameterless (def
orval
) membersisEmpty: Boolean
andget: V
,then:
PT1 = V
.V
must derive from a product typeProduct{n}[V1, ..., Vn]
andPTi = Vi
, fori = 1,..,n
.If
U
is of typeBoolean
andn = 0
, OKOtherwise error.
If the precondition (1) does not hold (i.e. no
unapply
method with the right argument type), but the companion objectP
contains a memberdef unapplySeq(x: T): U
whereX
conforms toT
thenU
derives fromSeq[V]
for some typeV
, thenPTi = V
fori = 1,..,n
, orPTn = V*
ifPn
is a repeated parameter.U
has parameterless (def
orval
) membersisEmpty: Boolean
andget: S
,where
S <: Seq[V]
for some typeV
, thenPTi = V
fori = 1,..,n
, orPTn = V*
ifPn
is a repeated parameter.Note 1: There are some subtleties with overloading which are skimmed over here. See the comment of typer.Applications#trySelectUnapply for a more detailed explanation.
Note 2: A consequence of the rules is that a selector type may match patterns of different arities using the same
unapply
. One arity could trigger a product based selection (using rule 1.i), the other a get/isEmpty selection (using rule 1.ii). Scala parser combinators actually exercise that functionality. A test case is inpos/Patterns.scala
.The text was updated successfully, but these errors were encountered: