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.




Reply via email to