Two new draft pattern matching JEPs

John Rose john.r.rose at oracle.com
Sat Mar 6 00:09:06 UTC 2021


I did careful pass over the docs and here are a couple
more comments.  You anticipated them at the end
with the “here’s what else we might do” section.

The “as” pattern which binds a value before doing
more pattern matching on it should can be synthesized
from “var” and “&”, as “P & var x”.  The rules for
inferring “var” types should take into account
left context as much as possible; I don’t think
that’s all there yet.  (I think “var x & P” is a
novice’s error, since the inferred type is poor.)

To make it easy to use I suggest that “var x = P”
be sugar for “P & var x”, and the same if “var”
is replaced by a type name.

I think you want don’t-care patterns, and “var _”
recommends itself pretty strongly.  Perhaps bare
“_” is sugar for “var _”, or maybe there’s no need.

You noted that array patterns sometimes want to
refer into the middle of the array.  I think that you
can do this with the array-index designator syntax
you mention, but perhaps it can bye done more
economically by allowing the ellipsis “…” to take
an optional anchoring index, to its right:

{ …[8], eightElement, ninthElement, … }

int[] a & { first, second, …[a.length-2], penult, last }

In some cases (including that last one) the [N] can be
inferred, and should be.  Thus, the trailing … your
document supports now is revealed to be …[a.length-N],
where N is the (statically determined) length of everything
before the ellipsis.

I think I like adding an anchor to “…” better than
having an ad hoc random access { [n] -> P } syntax,
because it makes visual accounting of the whole
array, from left to right.  But I can see arguments
for the random-access form (it doesn’t have to be
left-to-right).

If and when we do special construction expression syntax
for list, map, set, and 99 other user-defined types (I’m
serious about the 99; that’s a lower limit) then we will
want to make associated pattern syntaxes available.
The array stuff is a harbinger of this, since (as is rightly
so) the construction syntax new int[]{stuff} is associated
with the deconstruction syntax which is exactly the
same, except (a) the “new” is gone, and (b) the “stuff”
is pattern-land instead of expression-land.

Regarding the switch-case syntax, I think you have
done a good job finely dividing out the syntaxes.

You mention constraints that force switches to be
either pattern switches or non-pattern switches.
(This is near the example with “error1”.)

Maybe this could be expressed by documenting
three super-classes of switch cases:  pattern,
non-pattern, and either.  Then the rule boils
down to saying that a switch may not have
cases which are pattern cases and also cases
which are non-pattern cases.  At present there
are wordy lists, which are hard to keep straight.

For a non-pattern switch, you conservatively
left out “case null,1,2,3:”.  I think that’s too
conservative.  I won’t always want to route
null to the default case.

By adding “default” as a pseudo-case-label,
you made me remember that sometimes
I write switches like this:

switch (color) {
case RED:  return “red”;
case BLUE: return “blue”;
case NO_COLOR: //beware fallthrough
default:
  return “nothing of interest”;
}

Adding “case NO_COLOR” here is purely for show,
but sometimes you need some extra show, to help
the reader reason about special values (such as
NO_COLOR).  Converting to the rule form to
avoid fall through, I want:

switch (color) {
case RED ->  return “red”;
case BLUE -> return “blue”;
case NO_COLOR, default ->
  return “nothing of interest”;
}

Now null is also a special value, so I might
also want:

switch (color) {
case RED ->  return “red”;
case BLUE -> return “blue”;
case null, NO_COLOR, default ->
  return “nothing of interest”;
}

(You started it, and I’m rounding up a few more
use cases.)

> 2. The scope of a pattern variable declaration occurring in a case label of a switch labeled statement group, where there are no further switch labels that follow, includes the block statements of the statement group

suggest s/follow/immediately follow/

> On the other hand, falling through a label that does not declare a pattern variable is safe. 

You might want to point out that in “test6” that
“s” is no longer in scope after the default label.
I didn’t see it clearly explained, though it must be
true.

Thanks for this great work!

— John


More information about the amber-spec-experts mailing list