I want to separate the discussions about & between patterns and true()/false() 
aka mix pattern and expressions,
because the later is a call for trouble for me, the former is just a question 
about adding a new pattern or not.

I see true() and false() has an heresy because conceptually a bunch of patterns 
is a kind of declarative API while expressions are not.

If it helps, let me trace the story of where the true/false pattern idea came from.  We have had "method patterns" (need a better name) in the model forever; we have anticipated that some method patterns (e.g., map get, regex match) will distinguish between input and output parameters.  And we have imagined AND and OR combinators for a long time as well.

One day, it occurred to me that, with the ultimate pattern model we are envisioning, we don't need a linguistic notion of guards at all!  I could write an ordinary pattern:

    static pattern guard(boolean b) {
        if (!b) __FAIL;
    }

and voila, we can express guards as:

    case P & guard(e):

This was a powerful realization, because it meant that the notion of "guard" was "not a primitive"; it was something we could compose from existing envisioned tools.  Except, we don't have method patterns yet (and are not ready to do them), so ... why not treat the existing reserved identifier `true` as if it were declared like `guard` above?

(What's weird about this pattern is that it ignores its target. That's "clever", and clever can be confusing.)

I don't say this to justify the syntax; I get that pressing `true` into service may feel a bit of a stretch.  My point here is that the true/false patterns proposed in the JEP are *not special*; the are something we could declare eventually with the model that we expect to get to.  (They're like record patterns, in a sense; eventually all classes will be able to declare deconstruction patterns, but records are special in that they get one even without declaring it.)  So if you find them heretical, then you should also have a problem with expressing map-get or regex match as a pattern, no? And if so, let's put the complaint where it belongs; the use of expressions in true/false is just a symptom of your distress, not the cause.  Let's talk about the cause.

Allowing expression right inside a pattern means that you can witness the 
evaluation order of patterns, something we don't want.

Note that this is unavoidable when we get to declared patterns; if there are side effects, you can witness their order and arity.  But, this is also not your real point.  So, let's get to the real point, so we can discuss that, because whether we leak an unspecified order of evaluation through side-effects is mostly a distraction.

There is a misunderstanding here, i'm referring to the fact that
   case Point(1, 1):
is actually rejected because it's too much like new Point(1,1) but at the same 
time, you want to allow expressions in the middle of patterns.

Actually, the opposite!

A lot of people (initially, me included) would like to just interpret a boolean expression as a pattern:

    case Foo(var x, var y) && x > y: ...

I found that goal compelling, but as patterns get more complicated, this gets unreadable.  A main benefit of the true() patterns (or, the explicit guard() pattern declared above) is that it "quarantines" the expression in an expression wrapper; there's a clear boundary between "pattern world" and "expression world".

In any case, you are distorting the claim of "no expressions in the middle of patterns."  We have always envisioned specific contexts where expressions can be dropped into patterns (map get, regex), but we have worked to ensure there is a *clear syntactic division*, so that it is clear from the syntactic structure whether something is a pattern or an expression.

For (a), yes it's switch specific and it's great because we don't need it for 
instanceof, you can already use && inside the if of an instanceof and you don't 
need it when declaring local variables because the pattern has to be total. So being 
specific to switch is not really an issue.

Only true if `instanceof` and `switch` are the only contexts where you can imagine patterns. What about, say, `catch`?  If you nail a bag on the side of switch, you will have to nail the same bag on the side of catch.  Which might be acceptable, and the same bag might fit, but that's yet more ad-hoc language surface.

For (b), you can always shift all the contents of true() and false() to the 
right into a traditional guard, so we don't need true() and false()

In theory true, but only in a world where pattern evaluation is cost-free, exception-free, and side-effect free.  (That's why && is short circuiting -- because these things are not always true.)

I'm not deaf to the argument that "nailing a bag on the side will be easier for developers to accept", but please, let's stop pretending it's not a bag.  If you want to advocate for "bag", then please, make that case directly!


Reply via email to