Is case var(var x, var y) a valid syntax ?

forax at forax at
Sun Sep 13 11:21:00 UTC 2020

----- Mail original -----
> De: "Brian Goetz" <brian.goetz at>
> À: "Remi Forax" <forax at>
> Cc: "Guy Steele" <guy.steele at>, "Alan Malloy" <amalloy at>, "amber-spec-experts"
> <amber-spec-experts at>
> Envoyé: Mardi 8 Septembre 2020 15:53:36
> Objet: Re: Is case var(var x, var y) a valid syntax ?

>>  - Is either total or partial.  Deconstruction patterns are total; other patterns
>>  we'll be able to express later, such as `Optional.of(var x)`, are partial.
> While I don’t want to get into a deep dive on declared patterns now, let’s just
> say that they’ll exist and they’re important (Optional.of(var x),
> Optional.empty(), etc.)  So in increasing order of generality:
>    Type patterns:  T t
>    Deconstruction patterns: T(var x)
>    Declared patterns: Optional.of(var x)
> Remi would like to view deconstruction patterns as a generalization of type
> pattern, but they are more properly understood as a restriction of declared
> patterns — just as constructors can be understood as a restriction of methods.
> Because we haven’t seen much of declared patterns yet, it is easier to miss
> their role in the spectrum, but their role is pretty obvious once you step back
> and think about it.

see below

> Deconstruction patterns are constrained compared to declared patterns in:
> - their name (like constructors!)
> - They are total on their declaring class, so they are guaranteed to match (much
> like a constructor is guaranteed to not return null)
> - While instance members, they are not inherited (just like constructors)

At least you want a deconstructor to be overrideable (which is not fully equivalent to being inherited).
A deconstructor is for allowing encapsulation so the world projected by a deconstructor may have a little to share with how the the class are implemented

  class Employee {
    int baseSalary;

    deconstructor Employee(int salary) { return (baseSalary); }
  class VP extends Employee {
    int bonus;

    deconstructor VP(int salary) { return (baseSalary + bonus); }

  Vp vp = new VP();
  Employee employee = vp;
  employee instanceof Employee(salary) {
    System.out.println(salary);  // 2500

and here you can see that Employee(salary) is not a call to the deconstructor but an instanceof Employee + a call to the deconstructor (int salary) !

> - They can only be called via a pattern match (just as a constructor can only be
> called via a `new` operation.)

so unlike a constructor that can be called either by a new or by this(...) and super(...) a deconstructor can only be called vua pattern matching.

> The role of a constructor is to take an external state description, validate and
> normalize it, and produce an instance.

The role of a constructor is to hide the information of how a class is implemented. Only if all the fields are final it plays the role of the single gated entry point.

> The role of a deconstructor is to take an instance and produce an external state
> description.  (If the ctor has to copy mutable elements on the way in, the dtor
> is also likely to want to do the same on the way out.)

The role of a deconstructor is to hide the information of how the class is implemented and allow to pattern match to a projected form of the instance.

> In this way, both ctor and dtor mediate access between an external API and the
> internal representation.

It's only true for a constructor if the constructor (constructors) are the only way to change the value of an instance.
It's only true for a deconstructor if the deconstructor has a matching constructor

I start to think that calling a deconstructor a deconstructor is not the right term because while a constructor and a deconstructor can be dual of each other, this mirroring in not true in the general case,
it's only guarantee in the case of record because you have a canonical constructor.


More information about the amber-spec-experts mailing list