Composition of pattern questions

Brian Goetz brian.goetz at oracle.com
Wed Mar 3 22:51:03 UTC 2021



> 1) What are the use cases for combined patterns beyond pattern+guard?

I presume you are asking specifically about combining patterns with the 
AND combinator, since there's multiple ways to combine patterns.  But, 
this is sort of like asking "what are the use cases for a logical AND in 
the language" -- the whole point is to give developers tools for 
expressing the logic they want using regularized, combinable forms.

With patterns that operate on the totality of a target, like 
`Rectangle(Point x, Point y)`, you're right that you've already tested 
as much as you can about the structure of a target.  And, flipping it 
the other way, we can nest a Point deconstructor: `Rectangle(Point(var 
x, var y), Point p2)`.

But, there are also patterns that operate by focusing on an aspect of an 
aggregate.  Fetching a key from a map is a good example, as is parsing 
JSON/XML, as is any sort of query on a complex aggregate. As a 
motivating example:

     if (m instanceof (Map.withMapping("key1")(var v1) & 
Map.withMapping("key2")(var v2))) { ... }

Here, we are asking if the Map matches the _combined_ pattern associated 
with "has keys key1 and key2".  Could we express this without combining 
patterns with &?  Yes, but its harder and more error-prone, because what 
we want to express is the _conjunction_ of the two, and we want the 
match to succeed only if both are true.  If we had to test them 
individually, we'd end up with a larger state space and more 
opportunities to make errors.

Deconstruction patterns can also work on interfaces, so if you've got a 
system where you mix lots of interfaces together, & patterns work in the 
obvious way:

     if (x instanceof (Fooable(FooProvider fp) & Barable(BarProvider 
bp))) { ... use fp and bp ... }

> 2) Why do we need both true() and false() for guard patterns?

We don't; obviously you can derive one from the other.  But if we have 
only `true(e)`, people will surely ask "where is false(e)", and there 
are some things that are easier to express that way.

But maybe you're asking, why call them "true" and "false" in the first 
place?  Without inviting a syntax design discussion here, there are a 
number of reasons to propose this.  They are already keywords; people 
know exactly what they mean; and they are short. We could also invent a 
conditional keyword (e.g., "when", "where"), but that has its 
challenges, so we would prefer to use an existing keyword if there is 
one that fits.  (Re-using "if" is probably bad, though; it will likely 
to be too hard to tell where the case ends and a statement begins.)

> 3) Are OR patterns ever going to be needed?
>
> I know there has previously been discussion around OR patterns,
> however it has currently been ruled out. It seems to me that if OR was
> permanently ruled out (a choice which limits Java's future
> development, but perhaps in an acceptable way), then there are a few
> alternate syntax options.

It is most definitely not permanently ruled out.   OR patterns introduce 
the complication that a binding could have _multiple_ declaration 
points.  This is no problem from a language design or compiler 
perspective, but confusing to humans, and presents challenges for 
tooling (what should the IDE do when you ask for "go to declaration"?)  
Because the use cases for OR patterns are less immediate, it was a 
reasonable thing to defer.

In fact, as I mentioned on the other list, the main issue here is that 
most of the use cases for AND patterns are _also_ less immediate, except 
we had an immediate need for guards, which leaves us with a bad choice: 
expose a concept before the user base is really ready (engendering 
exactly the pushback you're delivering now), or, nail yet another ad-hoc 
bag on the side of switch, which will eventually become redundant 
because it will be expressible using more primitive concepts.

It sounds like your vote is "bag, please"?



More information about the amber-dev mailing list