New pattern matching doc
Brian Goetz
brian.goetz at oracle.com
Fri Jan 8 16:05:06 UTC 2021
> By example, case Optional.of() is called the static pattern in the
> document, but the corresponding member is not static at al, it has to
> have access to the values of the instance.
This is not correct. The pattern `Optional.of()` is truly static.
> I've proposed to call the patterns "patterns" and the corresponding
> class member "case methods" for that reason, you may prefer other
> names, but i think that making this separation is important.
Maybe. (Or maybe it's actively unhelpful, because you don't quite get
the model yet -- so let's make sure you understand the model fully first.)
Let me step back, and draw some connections between methods/ctors and
patterns. We currently have three kinds of executable members: ctor,
static methods, instance methods.
- Constructors have a receiver, are not inherited, and do not have
names. (Really, they don't; the class name is just a surface syntax
artifact, it could just as easily have been "new" or "constructor" (and
is erased to <init> in the classfile). When you say `new
ClassName(args)`, the identifier `ClassName` is the name of a class, not
a constructor.)
- Static methods have no receiver, are not inherited, and have names.
- Instance methods have a receiver and are inherited, and have names.
All patterns are "invoked" only through pattern matching (and perhaps
through reflection), not directly. There are many kinds of patterns,
and names in patterns go through various processes to map them to patterns.
case Foo f: // type pattern
case Foo(int x): // deconstruction pattern
case Foo.of(var x): // static pattern
case withMustard(var amount): // instance pattern
For `case Foo f`, this is a type pattern, and the `Foo` class is
uninvolved. The applicability test is just classic `instanceof`.
For `case Foo(int x)`, this is a deconstruction pattern, and Foo is the
name of a class, not of a pattern. Just like with constructors, we look
in class Foo (not superclasses) for a matching deconstructor. The
target becomes the receiver of the pattern invocation.
For `case Foo.of(var x)`, this is a static pattern. Foo is the name of
a class, and `of` is the name of a declared static pattern in Foo. The
target becomes an argument of the pattern invocation.
For `case withMustard(var amount)`, this is an instance pattern. We
look in the static type of `Foo` for an instance pattern called
`withMustard`. The target becomes the receiver of the pattern invocation.
Possibly orthogonally, some patterns are total on their target type, and
some are not. Totality is used in switches, and also in pattern-bind
statements; if we have a pattern bind
Point(var x, var y) = p
then the pattern used here must be total on the static type of `p`.
We could choose a model where all patterns had a `total` or `partial`
modifier, but after writing a bunch of code, it became clear that the
vast majority of deconstruction patterns are total, and the vast
majority of others are partial, and so it is a simplifying move to
"lump" and say "deconstruction patterns are always total; other patterns
are always partial." (This is a contingent choice, and could be
revisited later, once we write a lot more code.)
I think you're saying "we should treat deconstruction patterns as a
special case of static patterns." Not sure why you think that, maybe
that "having fewer kinds of patterns is simpler?" (If so, I think it's
not simpler -- I think its simpler to have a pattern that is dual to
constructor and structurally like constructors, and a static pattern
that is dual to static factories and structurally like static
factories.) Constructors and static factories are different; one has a
receiver, one does not; one has a name, one does not.
Does this help?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20210108/e4175144/attachment.htm>
More information about the amber-spec-experts
mailing list