<div dir="ltr">I have certainly experienced a double take when seeing true(expr). I can step back and recognize that it's just some arbitrary syntactical choice, and true(x) is evocative of the question "is x true?", but at first glance it is not appealing. Repurposing a language keyword in this way is surprising; it seems silly, but I think part of it is like, "my IDE has always used a different font for true than for method calls, and wouldn't it look weird to have something with that font have parentheses after it?". Obviously IDEs will adapt, and to complain about anticipated IDE font rendering would be even worse than Brian's usual bugbear about premature syntax discussions. I'm just getting at that true currently occupies a very specific place in my mental headspace, and I'm not sure that I'm happy to stretch it if all we get is the evocative "is x true?" reading.<div><br></div><div>I also don't really care for the natural symmetry with false. I'd rather have one way to express "protect this pattern-match clause with a guard" than two - I never was very excited by perl's `unless` keyword, for when you want to write an `if` but backward. If we had true(expr), we'd surely be asked to add false(expr), which sounds like an obvious feature but I don't imagine would lead to more readable code very often.</div><div><br></div><div>grobble seems fine. When discussion of switch patterns started, I was one of the people clamoring (quietly) for guards, and I imagined either a single operator or a single keyword separating the (entire) pattern from its guard expression (singular). But the idea of seeing guards as just a special kind of pattern, and for patterns to be composable with each other as a more general kind of guard, appeals to me. Being able to match two patterns against the same object (and-patterns) is actually a feature I thought Haskell and Scala already had, via their as-pattern - but it turns out you can only actually name a variable, not an entire pattern, in their as-pattern slot. In Clojure, at least, generally anywhere a variable name could be bound, you can bind a destructuring form instead - and this includes the :as slot. If we're going to have and-patterns (which, again, I think are nice), it seems quite neat to have guards be just a special case of that, and all it "costs" is that instead of a single keyword or operator separating guards we have an operator and then a keyword (later revealed to be an ordinary library pattern) separating the pattern from its guard.</div><div><br></div><div>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</div><div><br></div><div>switch (people) {</div><div>  case Pair(Person(String name1, int age1), Person(String name2, int age2))</div><div>  Â  | age1 > age2 -> name1 + " is older"</div><div>  Â  | age2 > age1 -> name2 + " is older"</div><div>  Â  | otherwise -> format("%s and %s are the same age", name1, name2)</div><div>}</div><div><br></div><div>Three cases, but you don't have to repeat the entire pattern three times, just guard the parts you care about. This makes it useful for guards to not just be degenerate patterns, but to be their own separate thing that can refine a pattern. With grobble and and-patterns I don't see a nice way of spelling this very useful feature. People often answer: "Just match the Pair once, extracting its variables, and write an if/else chain under it", but that doesn't combine very well with fall-through: if it's possible for all your guard clauses to be false you'd like to fall through to the next pattern (maybe when someone's name is "Brian" I want to fall through to a pattern handling Collection instead of Pair).</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 4, 2021 at 10:19 AM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  
    
  
  <div>
    <font size="+1"><font face="monospace">Lots of people (Remi here,
        VictorN on a-comments, StephenC on a-dev) are complaining about
        true/false patterns, but my take is that we've not really gotten
        to the real objections; instead, I'm seeing mostly post-hoc
        rationalizations that try and capture the objections
        (understandable), but I don't think we've really hit the mark
        yet.  As I've said, I believe there might be something "there"
        there, but the arguments made so far have not yet captured it,
        so I don't really know how to proceed.  But, clearly this has
        pushed people's buttons, so let's try to drill in.<br>
        <br>
        <br>
        One possible objection is indirectness / discoverability; that
        to refine a pattern, you have to find some other pattern that
        captures the refinement, and combine them with an operator that
        isn't used for anything else yet.  This contributes to making it
        feel like an "incantation".  <br>
        <br>
        Another possible object is more superficial, but may be no less
        real.  I had a private exchange with AndreyN, which revealed two
        potentially useful bits of information:<br>
        <br>
        Â - It's possible that the bad reaction to true(e) is that,
        because we're so wired to seeing `true` as a constant, the idea
        of seeing it as a method/pattern name is foreign;<br>
        <br>
        Â - Because true is a reserved identifier, the possibility to
        later pull back the curtain and say "look, true(e) is not magic,
        it's just a statically imported declared pattern!" is limited. 
        So by picking true/false now, we miss an opportunity to unify
        later.  <br>
        <br>
        So, here's a thought experiment, not so much as a concrete
        proposal, but as a "how does this change how we think about it"
        query; imagine we picked another identifier, with the plan of
        ultimately exposing it to be just an ordinary method pattern
        later.  </font></font><font size="+1"><font face="monospace"><font size="+1"><font face="monospace">I'll use the obviously stupid
            "grobble" in this example, to avoid inclinations to paint
            the shed.  So you'd write: <br>
            <br>
          </font></font>    case Foo(var x, var y) & grobble(x >
        y): ...<br>
        <br>
        and in Java 17, "grobble" would be specified to be an ad-hoc
        guard pattern, but in Java N > 17, we would be able to pull
        back the curtain and say "behold, the long-hidden declaration of
        grobble, which we've conveniently static-imported for you": <br>
        <br>
        Â Â Â  static pattern(void) grobble(boolean expr) { <br>
        Â Â Â Â Â Â Â  if (!expr)<br>
        Â Â Â Â Â Â Â Â Â Â Â  __FAIL;<br>
        Â Â Â  }<br>
        <br>
        This would allow us to borrow from the future, while allowing
        the temporary hack to be turned into something legitimate
        later.  <br>
        <br>
        So, control question: if we had said "grobble" instead of
        "true", does that change the perception of how ugly, foreign, or
        roundabout<br>
        <br>
      </font></font><font size="+1"><font face="monospace"><font size="+1"><font face="monospace">    case Foo(var x, var y)
            & grobble(x > y): ...<br>
          </font></font><br>
        is?  <br>
        <br>
        Direct answers only, initially.<br>
      </font></font><br>
    <div>On 3/4/2021 12:05 PM, Brian Goetz
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <font size="+1"><font face="monospace">Received on the -comments
          list.<br>
          <br>
          Analysis from the legislative analyst: <br>
          <br>
          This comment amounts to "Well, if you could eventually write
          the true/false patterns as declared patterns which ignore
          their target, then just do declared patterns now, and just
          make them declared patterns."  (Which is exactly what kicked
          off this direction -- that guards could be expressed as
          declared patterns which ignore their target.)  <br>
          <br>
          When lumping the features together for a delivery, there's a
          balance to be struck, of delivering incremental value vs
          delivering the entire story at once.  The JEPs proposed at
          this point are pretty close to being a useful increment of
          value without overly constraining the remainder of the story,
          but guards are an area where it is tempting to "borrow from
          the future."  </font></font><font size="+1"><font face="monospace">Of course if we could do everything at once,
          we wouldn't be worrying about balancing the short term with
          the long.  </font></font><font size="+1"><font face="monospace">But, delaying further pattern matching
          progress until we have a full story for declared patterns
          seemed a bit extreme.  <br>
          <br>
          So it's not that we missed that route -- indeed, that's the
          route that got us to the current position -- it's just that
          route was rejected as "would delay delivering real value now."<br>
        </font></font>
      <div><br>
        <br>
        -------- Forwarded Message --------
        <table cellspacing="0" cellpadding="0" border="0">
          <tbody>
            <tr>
              <th valign="BASELINE" nowrap align="RIGHT">Subject:
              </th>
              <td>Re: Two new draft pattern matching JEPs</td>
            </tr>
            <tr>
              <th valign="BASELINE" nowrap align="RIGHT">Date:
              </th>
              <td>Thu, 4 Mar 2021 17:34:15 +0100</td>
            </tr>
            <tr>
              <th valign="BASELINE" nowrap align="RIGHT">From:
              </th>
              <td>Victor Nazarov <a href="mailto:asviraspossible@gmail.com" target="_blank"><asviraspossible@gmail.com></a></td>
            </tr>
            <tr>
              <th valign="BASELINE" nowrap align="RIGHT">To: </th>
              <td><a href="mailto:amber-spec-comments@openjdk.java.net" target="_blank">amber-spec-comments@openjdk.java.net</a></td>
            </tr>
          </tbody>
        </table>
        <br>
        <br>
        Hello Java experts,<br>
        <br>
        I've been following the discussion about new JEPs for pattern
        matching and<br>
        I've observed a controversy considering the introduction of
        Pattern guards.<br>
        <br>
        It seems that what Brian Goetz stated as a problem is:<br>
        <br>
        <blockquote type="cite">
          <pre> * either we
   don't provide a way to write guarded patterns now (which is not a
   problem for instanceof, but is for switch), or
* we nail some bit of terrible syntax onto the switch that we're stuck
</pre>
        </blockquote>
        with.<br>
        <br>
        But from my understanding this misses another route:<br>
        <br>
        <blockquote type="cite">
          <pre>We've already discussed how some patterns (e.g., regex) will take input
arguments, which are expressions.  We haven't quite nailed down our
syntactic conventions for separating input expressions from output
bindings, but the notion of a pattern that accepts expressions as input
is most decidedly not outside the model.
</pre>
        </blockquote>
        <br>
        When patterns with arguments become available users are able to
        write code<br>
        like the following (with imaginary syntax).<br>
        <br>
        ````<br>
        String s = "aabb";<br>
        String result = switch (s) {<br>
        case String.["(a+)(b+)"]matches(var as, var bs) -> bs + as;<br>
        default -> "no match";<br>
        }<br>
        ````<br>
        <br>
        Having this ability nothing prevents users to define a `guard`
        pattern in<br>
        their library and to use it like:<br>
        <br>
        ````<br>
        case Rectangle(Point x, Point y) & Utils.[x > 0
        && y > 0]guard()<br>
        ````<br>
        <br>
        For me it seems a good solution to introduce a more general
        mechanism<br>
        (patterns with input arguments) and use it to define a library
        `guard`<br>
        pattern then to nail some additional syntax (true/false
        overload).<br>
        <br>
        So returning to the original problem then I think a possible
        solution is to<br>
        introduce some special `guard` library pattern right away.<br>
        <br>
        Cons:<br>
        * Need to decide on special syntax for input arguments right
        away<br>
        * Hard to specify that custom patterns with input arguments are
        not yet<br>
        available and only special library `guard` patterns can use this
        feature.<br>
        <br>
        Pros:<br>
        * Less special syntax in the language, because input arguments
        are going<br>
        to be introduced anyway<br>
        * It is probably easier to explain to users the usefulness of
        `&` because<br>
        that way users can already see that not only destructuring
        pattern are<br>
        going to be available, but more generic and complex patterns
        with input<br>
        arguments are going to be available.<br>
        <br>
        --<br>
        Victor Nazarov<br>
      </div>
    </blockquote>
    <br>
  </div>

</blockquote></div>