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