<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Gavin Bierman" <gavin.bierman@oracle.com><br><b>To: </b>"Remi Forax" <forax@univ-mlv.fr><br><b>Cc: </b>"Brian Goetz" <brian.goetz@oracle.com>, "amber-spec-experts" <amber-spec-experts@openjdk.java.net><br><b>Sent: </b>Friday, January 26, 2024 1:36:22 PM<br><b>Subject: </b>Re: Towards member patterns<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<font face="Menlo">Hi Remi,</font><br id="lineBreakAtBeginningOfMessage">
<div><br>
<blockquote>
<div>On 26 Jan 2024, at 11:08, Remi Forax <forax@univ-mlv.fr> wrote:</div>
<br class="Apple-interchange-newline">
<div>
<div>Let's retry.<br>
<br>
I think your proposal solves the cases where the type you are switching on is closed (final, sealed) but not if the type is open (non-sealed).<br>
<br>
Let's take an example, let suppose I've the following hierarchy<br>
<br>
 public sealed interface Tree {<br>
   static Tree none() { return None.NONE; }<br>
   static Tree cons(Tree tree) { return new Cons(tree); }<br>
 }<br>
 private enum None implemnts Tree { NONE }<br>
 private class Cons implements Tree {<br>
   private final Tree tree;<br>
<br>
   private Cons(Tree tree) { this.tree = tree; }<br>
 }<br>
<br>
If I want to have a static method children that returns all the children of the Tree, using the pattern matching I would like to write<br>
<br>
 static List<Tree> children(Tree tree) {<br>
   return switch(tree) {<br>
     case Tree.none() -> List.of();<br>
     case Tree.cons(Tree child) -> List.of(child);<br>
   };<br>
 }<br>
<br>
And inside Tree, i can add the following inverse methods<br>
<br>
   static inverse Tree none() { if (that == Tree.NONE) __yield (); }<br>
   static inverse Tree cons(Tree tree) { if (that instanceof Cons cons) __yield (cons.tree); }<br>
<br>
As I said, it works great with a closed hierarchy, but now let suppose the hierarchy is not sealed, if the hierarchy is not sealed, having static factories make less sense because we do not know all the subtypes. So we have<br>
<br>
 public interface Tree {}<br>
 public enum None implemnts Tree { NONE }<br>
 public class Cons implements Tree {<br>
   private final Tree tree;<br>
<br>
   public Cons(Tree tree) { this.tree = tree; }<br>
 }<br>
<br>
and in the future, someone may add<br>
 public class Node {<br>
   private final Tree, left, right;<br>
<br>
   public Node(Tree left, Tree right) { this.left = left; this.right = right; }<br>
 }<br>
<br>
Because the hierarchy is open, we need to use the late binding here.<br>
So i may rewrite children like this<br>
 static List<Tree> children(Tree tree) {<br>
   return switch(tree) {<br>
     case that.extract(List<Tree> list) -> list;   // wrong syntax, it's just to convey the semantics<br>
   };<br>
 }<br>
</div>
</div>
</blockquote>
<div><br>
</div>
<div><br>
</div>
<div>
<div><font face="Menlo">Already here I would disagree. I think you have missed the abstraction. You</font></div>
<div><font face="Menlo">want all `Tree` instances to support an instance pattern member (I think of an</font></div>
<div><font face="Menlo">instance pattern member as a *view*, which I find quite suggestive)? Then you </font></div>
<div><font face="Menlo">need to say it, e.g.:</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">  public interface Tree {</font></div>
<div><font face="Menlo">    pattern Parent(List<Tree> children);  // all trees can be viewed as a </font></div>
<div><font face="Menlo">                                          // parent with children</font></div>
<div><font face="Menlo">  }</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">Now your `None` and `Cons` classes will be required to implement this instance</font></div>
<div><font face="Menlo">pattern member, i.e.</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">  public enum None implements Tree { NONE </font></div>
<div><font face="Menlo">    pattern Parent(List<Tree> children) {</font></div>
<div><font face="Menlo">      children = List.of();</font></div>
<div><font face="Menlo">    }</font></div>
<div><font face="Menlo">  }</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">  public class Cons implements Tree {</font></div>
<div><font face="Menlo">    private final Tree tree;</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">    public Cons(Tree tree) { this.tree = tree; }</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">    pattern Parent(List<Tree> children) {</font></div>
<div><font face="Menlo">      children = List.of(tree);</font></div>
<div><font face="Menlo">    }</font></div>
<div><font face="Menlo">  }</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">Then you can rewrite your `children` static method (although it is perhaps a</font></div>
<div><font face="Menlo">little defunct):</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">  static List<Tree> children(Tree tree) {</font></div>
<div><font face="Menlo">    return switch(tree) {</font></div>
<div><font face="Menlo">      case Parent(List<Tree> children) -> children; </font></div>
<div><font face="Menlo">    };</font></div>
<div><font face="Menlo">  }</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">The switch is exhaustive because the `Parent` view is total (by the absence of </font></div>
<div><font face="Menlo">the </font><span style="font-family: Menlo;">`partial` modifier - maybe we'll insist on `total`, TBD). </span></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">Now you can freely extend the hierarchy, and your `children` static method will</font></div>
<div><font face="Menlo">work without modification:</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">  public class Node implements Tree {</font></div>
<div><font face="Menlo">    private final Tree left, right;</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">    public Node(Tree left, Tree right) { this.left = left; this.right = right; }</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">    pattern Parent(List<Tree> children) {</font></div>
<div><font face="Menlo">        children = List.of(left, right);</font></div>
<div><font face="Menlo">    }</font></div>
<div><font face="Menlo">  }</font></div>
</div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">(Perhaps a better implementation would be to declare a *partial* `Parent` view </font></div>
<div><font face="Menlo">and </font><span style="font-family: Menlo;">then have `None` fail, but I leave that to your imagination. This approach</span></div>
<div><font face="Menlo">still works.)</font></div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">Or did I misunderstand your example?</font></div></div></blockquote><div><br></div><div>I don't think so,you got it.</div><div><br data-mce-bogus="1"></div><div>What was not clear is how the compiler links the pattern Parent to the pattern method Parent(List<Tree>) inside Tree.<br data-mce-bogus="1"></div><div>Thanks to the mail of Brian, the answer is either "case Tree.Parent(List<Tree> children) -> ..." or "case tree.Parent(List<Tree> children) -> ...", both will work.</div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div>
<div><font face="Menlo"><br></font></div>
<div><font face="Menlo">Gavin</font></div>
</div></blockquote><div><br></div><div>RĂ©mi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div></div></div></body></html>