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?

Reply via email to