[External] : Re: Fwd: Two new draft pattern matching JEPs

Brian Goetz brian.goetz at oracle.com
Fri Mar 5 16:29:17 UTC 2021


>
> The one objection I still have to grobble is one I've raised before: 
> it makes it hard to imagine ever representing disjunctions as guards. 
> I always bring up stuff like
>
> switch (people) {
>   case Pair(Person(String name1, int age1), Person(String name2, int 
> age2))
>     | age1 > age2 -> name1 + " is older"
>     | age2 > age1 -> name2 + " is older"
>     | otherwise -> format("%s and %s are the same age", name1, name2)
> }
>

If we can assume that such "sub-switches" are routinely total on the top 
pattern, I think we can do this with the tools on the table, perhaps 
with some small adjustments.

Note that for deconstruction patterns, you can bind to the top-level 
result.  This means you can further switch on it.  If we can use 
grobble(e) as a case label without a pattern (which makes sense under 
either the interpretation that grobble(e) is a pattern, or that it is a 
feature of case), we can write your above as:

     switch (people) {
       case Pair(Person(String name1, int age1), Person(String name2, 
int age2)) p ->
           switch (p) {
               case grobble(age1 > age2) -> name1 + " is older";
               case grobble(age2 > age1) -> name2 + " is older";
               default -> format("%s and %s are the same age", name1, 
name2);
           }
     }

which isn't too bad.  Sometimes we will want to further match on `p` (if 
I was factoring cases P&Q and P&R), but in this case I'm just factoring 
guards so the use of `p` here is mostly noise.  We could consider 
allowing you to drop the switch operand and rewrite as

     switch (people) {
       case Pair(Person(String name1, int age1), Person(String name2, 
int age2)) ->
           switch  {
               case grobble(age1 > age2) -> name1 + " is older";
               case grobble(age2 > age1) -> name2 + " is older";
               default -> format("%s and %s are the same age", name1, 
name2);
           }
     }

in that case.  A switch with no target can only contain grobble cases; 
perhaps in that "case" we allow you to elide the grobbling:

     switch (people) {
       case Pair(Person(String name1, int age1), Person(String name2, 
int age2)) ->
           switch {
               case age1 > age2 -> name1 + " is older";
               case age2 > age1 -> name2 + " is older";
               default -> format("%s and %s are the same age", name1, 
name2);
           }
     }

All of this is switch-golf, but the point is that the use case of 
factoring P&Q and P&R is one that is handled reasonably well by nested 
switches already, if we had a functioning switch guard mechanism and our 
sub-switches are total.  If the sub-switches are total, you'd need a 
real guard to capture the union of the guards, which might not be so 
great, but I suspect (based on the fact that this idiom comes from 
Haskell, and most piecewise decompositions in Haskell end with an 
otherwise) that this is more of a corner case.






More information about the amber-spec-experts mailing list