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