New pattern matching doc
forax at univ-mlv.fr
forax at univ-mlv.fr
Mon Jan 11 17:01:08 UTC 2021
> De: "Brian Goetz" <brian.goetz at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Envoyé: Lundi 11 Janvier 2021 16:38:31
> Objet: Re: New pattern matching doc
>>>> 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.
>> The pattern is static, but perhaps not as "static" in a static method call, but
>> as "static" in a method reference way.
>> For Optional.of(var x), the implementation needs to take a look to the content
>> of the Optional, thus the implementation is not static as in static method.
> For static patterns, the target is passed as an argument. Just like the
> following method:
> class Foo {
> static<T> T unboxIfPresentOrNullIfAbsent(Optional<T> target) {
> return target.isPresent() ? target.get() : null;
> }
> }
> This is a static method that "matches" present optionals, and returns their
> contents if present, or a sentinel if not. The static pattern Optional::of does
> the same, just not as a method.
It can not, for several reasons, first you should be able to declare a "virtual" pattern method on an interface and a class that implements that interface should provide a specific implementation of that pattern.
Otherwise you are re-enacting the game "extension method vs default method" but with a different outcome.
Moreover, you can not access to super class members (via super) if the method is a static method.
That's why a lambda like () -> super.x is desigared to an instance method and not a static method.
[...]
>>> 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.
>> The application test is an instanceof + a call to the deconstructor which as a
>> special linking semantics for transferring the bindings
> I am not sure I like the word "call" here, as it suggests that you are trying to
> cast these things as methods. Under the hood, of course there are going to be
> methods, because that's what the JVM offers us. But we're talking about the
> language model here, so I'd like to avoid confusing words. But yes, it is as if
> we are "calling" the deconstructor which puts the bindings somewhere the
> "caller" can get them.
>>> 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.
>> The application test is an instanceof + a call to the method an instance method
>> of() with, i hope, the same special semantics for transferring the bindings.
> Same transfer of the bindings, but it is not an instance method; static patterns
> translate to static artifacts. The switch target (the Foo) is passed as an
> ordinary parameter. Then, there is an additional wrinkle on the bindings
> transfer, because the pattern might say "nope, not really a Foo of anything",
> in which case we "transfer" a sentinal that says "these bindings are no good,
> don't use them."
>> Unlike the deconstructor, this instance method can be overridden (you want to be
>> able to declare such method on an interface).
> No, but instance patterns can.
>> It's more that i want that all patterns that have bindings to share the same
>> meta-protocol (the way to bind bindings).
> That is how this works. Here's the full (abstract) protocol.
> - Every pattern has a target, which is "passed" from the client to the pattern.
> - Every pattern can have zero or more output bindings, which are "passed" back
> from the pattern to the client.
> - Patterns can succeed or fail. In case of failure, they return no bindings.
> - Some patterns are constrained to never fail (total patterns.)
> - Patterns may take additional (input) arguments. (Canonical example: a "regex"
> pattern that takes the regex pattern as well as the target.)
> Different patterns use different subsets of this protocol. Total patterns don't
> make use of the "might fail" channel; none of the patterns so far make use of
> the "extra args" channel.
Yes, we agree on this part
> This maps to instance/static in a straightforward way: for instance patterns,
> the target is the receiver, for static patterns, it is passed as the first
> input argument.
And here we disagree because you are mixing how the pattern is used inside the switch with how it is declared inside the class.
When you use a pattern inside a switch, you have to specify the type because you may first have to do an instanceof, but it doesn't mean that the method that declare the pattern has to be static.
>> But a constructor neither need a special keyword nor have a semantics different
>> from a classical methods
> But this is just not true! Constructors are different in both syntax and
> semantics from classical methods.
You have butchered my original email on that part, i was just saying that in term of linking all pattern methods (destructor, static pattern implemented using an instance method or a static methods), they all should be presented the same way for a user that want to declare them.
> If I had to read between these pages of indirect objections, I'm tempted to
> guess that this is all really just: "I'm disappointed that we didn't make
> constructors just be static methods in the first place, and I want to fix that
> mistake now?"
Nope,
I'm not disappointed at all, i think we are slowly going to the right direction.
Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20210111/1d978a8d/attachment-0001.htm>
More information about the amber-spec-experts
mailing list