New pattern matching doc
Brian Goetz
brian.goetz at oracle.com
Mon Jan 11 21:37:34 UTC 2021
> To summarize, this is what i'm proposing,
> using the same notation as Alan, we have two syntax
> IDENTIFIER(BINDINGS), the unqualified pattern, and
> Qualifier.IDENTIFIER(BINDINGS), the qualified pattern.
Your previous mails seemed to focus on the declaration site, but now I
think you're talking about how we connect the use site to a
declaration. That's an area which the document didn't fully cover, so
good, let's talk about that.
Positing that there are three "kinds" of patterns -- deconstruction,
static, and instance -- we need to map the use-site description of a
pattern to a selected pattern declaration, not unlike overload
selection. The doc didn't provide rules for that, but its a fair
question. Let's do some examples.
X x = ...
switch (x) {
case Foo(var x): // probably a deconstruction pattern
case foo(var x): // probably an instance pattern in X *
case X.foo(var x): // either an instance or static pattern on X
}
Obviously, we can't take capitalization into effect, so we'll need some
priority order for disambiguation. (If we allow dispatch to local
patterns, or static import of patterns, these will fall into the second
bucket too.) And in all cases, we will have to be prepared to do some
overload selection on patterns, since there might be multiple with the
same name.
If this is what you are proposing, we are already on the same page
(modulo patterns that have explicit input arguments -- some syntax is
needed for that at the use site, but I've deliberately not gone there
yet, because we're still nailing down the model conceptually.)
> For the qualified pattern, Qualifier.IDENTIFIER(BINDINGS) references
> - either an instance method inside the class Qualifier, with 'this'
> being the value switched upon
> - or a static method inside the class Qualifier, the first parameter
> containing the value switched upon
If by "instance method" or "static method", you mean "instance pattern"
or "static pattern", then you've got this exactly right.
> For the unqualified pattern, IDENTIFIER(BINDINGS), it is equivalent to
> - AnotherType(BINDINGS) if the identifier is the type AnotherType
> (it's the deconstruction pattern)
> - either Type.IDENTIFIER(BINDINGS) and the rules above applied (it's
> the inference rule of Tagir)
> - or AnotherType.IDENTIFIER(BINDINGS) if there is an import static
> AnotherType.IDENTIFIER
Right, this is the universe of choices, we may want to prune the list if
we decide that (say) static import of patterns isn't helpful.
So I think you have correctly intuited the mapping from use-site
[Qualifier.]PatternName(BINDINGS) that I had in mind.
Now, a few words about overload selection. We have to declare what it
means for a pattern to be applicable to a "pattern invocation". This
includes:
- compatibility of the target
- compatibility of the input arguments
- compatibility of the bindings
For the target, this was outlined in the "Pattern Matching - Semantics"
document. For the input arguments, this will be lifted straight from
overload selection. For the bindings, these must agree in arity (unless
it's a varargs pattern), and the type at the use site must be compatible
with the declared type. (Though most of the time, the type at the use
site will be `var`, so I expect in practice, we'll mostly see
overloading on arity.) I suspect further that we'll borrow similar
treatment of varargs from overload selection (prefer non-varargs to
varargs).
More information about the amber-spec-experts
mailing list