New [draft] JEPs for Pattern Matching

Brian Goetz brian.goetz at
Thu Dec 13 01:33:43 UTC 2018

> Without
> clarity on the semantic choice for additional tests of the pattern ("when"
> clauses or && or something else), it feels premature to pursue if/else
> statements with patterns.

This argument feels exactly backwards to me.  Conditional statements _already_ have all the means necessary to express refined tests — the && operator — they don’t need to invent a new mechanism.  (Plus lots of other things.)  Whereas for switch, because switch’s legacy is rooted in exact constant equally, we may need to augment its decision-making ability in some way (which is unfortunate).  

If you want to refine this:

> if (foo instanceof Integer i)  // i now in scope

This is easy and natural without adding any new linguistic forms:

    if (foo instanceof Integer i && i > 0) { … }

Composing existing, already-understood mechanisms is far better than inventing new ones.  Everyone already knows what &&’ing two boolean expressions means, and it works in all the places where boolean expressions are allowed. 

> But this gets much more complex when there are multiple predicates,
> negations and else clauses. It is certainly possible to write some obtuse
> code [1].
> My feeling is that building on `instanceof` and allowing it to apply
> patterns anywhere could well be the wrong direction of travel. It doesn't
> seem completely unreasonable to restrict pattern predicates, rather than
> allowing them everywhere.

> if (foo case Integer i when i > 0) // i now in scope
> else if (foo case Integer i) // i now in scope
> else if (foo case Double d) // d now in scope

So what you’ve invented is a weaker form of `instanceof`, with an ad-hoc way to refine it with exactly one boolean criteria (but not broaden it with ||, for example).  And then you have to prevent (for what reason?) further combining this result using && or ||?  That’s not making the language simpler; it’s making it more complicated, and less expressive at the same time.  

It sounds to me like you saw some code that did something new, that new felt scary, and your first instinct was to find a way to constrain it.  But that’s often exactly the wrong response!  Where it led you — let’s make a new kind of expression (with a new kind of qualifier) that is almost like what we have but different, with new restrictions — will surely lead to both less expressiveness and _more_ complexity.  (What usually wins here is going in the other direction — trying to find how it blends into the existing language _more_ deeply.)

(As just one example of the sort of thing that your proposal makes unnecessarily harder, you can’t match two things at once: 

    if (o1 instanceof Foo(var a) 
        && o2 instance of Bar(var b)) { … }

This seems a gratuitous and unnecessary restriction, and will surely lead to more complex code as people try to work around it.)  

So, let’s back up.  Almost all of your note was about a solution, but what’s missing is what’s motivating you to propose this particular solution.  It’s almost always more useful to share your perception of a _problem_ than a proposed solution.  (Maybe the problem isn’t really a problem, in which case the solution isn’t needed.  Or maybe theres a better solution, but without a shared understanding the problem, we can’t really evaluate your solution.)  You alluded to the possibility of writing obtuse code — but, even if obtuseness were objective, the possibility that someone might write confusing code is not a reason to arbitrarily constrain the language.  

So, let’s start over.  What _problem_ you are concerned about?

More information about the amber-dev mailing list