Can pattern methods be total ?

forax at univ-mlv.fr forax at univ-mlv.fr
Tue Jan 26 14:36:53 UTC 2021


----- Mail original -----
> De: "Brian Goetz" <brian.goetz at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>, "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Envoyé: Lundi 25 Janvier 2021 13:58:56
> Objet: Re: Can pattern methods be total ?

> I don't necessarily mind if we get to a world where member patterns can
> be total.  (On the other hand, I don't mind if we never do, either.)
> The "dtors are total, others are partial" is a lump move, which is a
> good-enough-for-now-and-maybe-forever approximation.  If we are
> considering allowing totality to be denoted elsewhere, adding the
> ability to modify patterns later as total is an entirely reasonable
> option to preserve, and I don't think we've closed that off.
> 
> That said, I don't think that means we can shift the axes as you
> suggest.  Deconstructors are different from instance patterns in far
> more ways than just being total:
> 
>  - Deconstructor patterns are not inherited
>  - Deconstructor patterns do not have names
>  - Deconstructor patterns cannot be overridden, or abstract
>  - Deconstructor patterns cannot have input parameters
> 
> Only the last still makes sense if you s/deconstructor/total/.
> Constructors are special in the language, for better or worse; their
> duals are too.

I've certainly a more runtime oriented approach, everything the runtime needs to link in order to perform pattern matching are what i call pattern methods. 

Inside a class, there are 3 kinds of pattern method:
- deconstructor pattern method
- static pattern method
- instance pattern method

All other them are able to specify bindings.
All have a name, for a deconstructor, like for a constructor, the name is the class name,
static and instance can have input parameters.
instance only can be abstract/inherited/overriden.
instance and static can be partial or total, deconstructors are total.
for records, the compact deconstructor doesn't have to specify the bindings because they can be derived from the declaration.

Having bindings + totality and the way to call it is what separate a method from a pattern method.

[...]

> 
> We need to define override and method selection rules anyway; existing
> rules for methods take modifiers into account (can't override instance
> with static, or public with private), so totality constraints fit pretty
> easily.

Rémi

> 
> On 1/25/2021 7:32 AM, Remi Forax wrote:
>> The last document sent by Brian split patterns in two categories, deconstructor
>> and method patterns.
>> I would like to propose another way to see patterns, along the axis of partial
>> vs total pattern.
>>
>> A total pattern is a pattern that always succeed and bind the bindings.
>> A partial pattern is a pattern that may succeed or not and if it succeed bind
>> the bindings.
>>
>> Currently Brian proposes that all destructors are total patterns and all method
>> patterns are partial patterns.
>> While i agree for the former, as a user I will be surprising if "instanceof
>> Point(var x, var y)" can fail not because it's not a Point but because the
>> deconstruction did not succeed.
>> I disagree with the later because having total method patterns is useful, by
>> example you may want to be able to see a Point in cartesian coordinates or in
>> polar coordinates. You can not use a deconstructor here because in both cases
>> the bindings are two doubles, so you need a name to disambiguate between them.
>> Something like
>>    class Point {
>>      ...
>>      total pattern [double, double] polar() { ... }
>>      total pattern [double, double] cartesian() { ... }
>>    }
>>    
>> Here "total" means that the compiler can reject patterns with the same prefix
>> that both use different total nested patterns on the same class. It also means
>> that the compiler will enforce that body on the pattern method always "assign"
>> values to the bindings (also allowing infinte loops and throws).
>>
>> If we go in that direction, we also need to introduce a rule for overriding, if
>> a pattern method is declared total, all its overriden methods must be marked
>> total (enforced by both the compiler and the VM).
>> So if a pattern method is not total it can be overriden by a pattern method
>> marked total but the reverse is not possible.
>> Note that in term of compilation strategy this may requires a bridge method so
>> we may decide to have a stricter rule, i.e. a pattern method that override a
>> pattern method must have the same "totality".
>>
>> Another reason to know if a pattern is total or not is when we will introduce
>> patterns at local variables declaration site.
>>    Point(var x, var y) = point;
>>
>> I think only total patterns should be allowed here.
>> So
>>    Point.polar(var x, var y) = point;
>> is ok but
>>    Optional.of(var value) = optional;
>> is not, because optional can be Optional.empty().
>>
>>
>> So can pattern methods be total ?
>>
> > Rémi


More information about the amber-spec-experts mailing list