<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">I think you are probably
thinking that "taking what is already possible at the top level
and allowing it in nested position" is somehow considerably
simpler than "constant patterns", and therefore a suitable
stopgap, but that's not the case. (Not only is it essentially
the same problem, but a stopgap always leaves the possibility we
will foreclose on getting to the real thing.) <br>
<br>
It is an unfortunate artifact of transition (ideally, temporary)
that a switch can mix "constant cases" and "pattern cases"; this
division adds spec complexity and user friction for no direct
benefit. <br>
<br>
As to null, since `null` is a literal just like `0`, we would
hope that this would fit cleanly into constant patterns as
well. <br>
</font></font><br>
<div class="moz-cite-prefix">On 11/8/2023 7:35 AM, Sebastian Fischer
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CALoEywP47v+7gJ0UQur_ydgCcuYas1F-O2wiaJt=W5j343K6EQ@mail.gmail.com">
<div dir="ltr">
<div>Thank you both for your responses!</div>
<div><br>
</div>
<div>I understand that more diverse kinds of nested patterns
interact with multiple other planned extensions and in order
to better understand those interactions, nested patterns have
been restricted to record patterns for now.</div>
<div><br>
</div>
<div>My question was less about constant patterns (or other
unfinished extensions) and more about taking what is already
possible at the top-level of a switch and allowing it also in
nested pattern positions (probably caused by my hope that the
notion of nested patterns could be extended incrementally with
each new extension at the top-level). The example of
refactoring a nested pattern into nested switches illustrates
my intuition quite well: that nested patterns would have the
same semantics as corresponding nested switches.</div>
<div><br>
</div>
<div>The idea of unifying top-level with nested possibilities
raises the question whether null patterns or even guards
should be available in nested patterns. But I restricted my
question to CaseConstant (in the currently supported form)
because that is the most obvious gap and it complicates
refactorings of empty records into enum constants. Personally,
I think nested guards could be quite confusing but there might
be a case for nested null patterns.<br>
</div>
<div><br>
</div>
<div>Your summary helped me get an overview of previous
considerations. I'll try to find more details in the archives
and am looking forward to future discussions in the context of
the mentioned JEPs.<br>
</div>
<div><br>
</div>
<div>Sebastian<br>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Tue, Nov 7, 2023 at 3:30 PM
Brian Goetz <<a href="mailto:brian.goetz@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">brian.goetz@oracle.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px
0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div> <font size="4"><font face="monospace">To add to this:
there are several categories of questions that we wanted
to settle before considering constant patterns (which
would (almost?) complete the rehabilitation of switch):
<br>
<br>
- Syntactic. If `0` is both a literal and a pattern,
then locutions like `f(0)` can either be method
invocations or pattern matches. It was not obvious in
the early days whether such ambiguities would pose
roadblocks for using patterns in other contexts. This
is seeming more viable now but we didn't want to
foreclose this path too early.<br>
<br>
- User perception. Related to the above, if it is not
obvious what `f(0)` means, even if the grammar can be
parsed unambiguously, it might make code harder to
read. So we might hold out for a syntax that is
somewhat wordier but more obvious. <br>
<br>
- Semantics. At the beginning, it was very much not
clear (to the point where our first ideas would have
been pretty wrong) what the semantics of matching a
constant are. JEP 455 has been working through those
issues, so we believe we now have a firm foundation for
the meaning of `0` as a pattern.<br>
<br>
- Alignment with switch. The "obvious" meaning of
constant patterns may or may not align with the
treatment of constants in switch today; this needs to be
worked through carefully, otherwise refactoring a switch
like:<br>
<br>
case Foo(k)<br>
case Foo(k')<br>
case Foo(k'')<br>
<br>
to a switch like<br>
<br>
case Foo(var x) { <br>
switch (x) { <br>
case k<br>
case k' <br>
case k''<br>
}<br>
}<br>
<br>
will have subtle asymmetries. <br>
<br>
So to sum this up, constant patterns are an "obvious"
addition, but which turn out to be very much non-obvious
when you consider all the connections with other
language features and future language directions. So
we've been waiting for these to settle.<br>
</font></font><br>
<div>On 11/7/2023 4:37 AM, Gavin Bierman wrote:<br>
</div>
<blockquote type="cite">
<pre>Hi Sebastian,
Yes, there has been some discussion about adding constant patterns if you look through the archive. There are interesting syntactic issues, but IIRC we have been waiting for the primitive type patterns feature to settle so we have a proper basis to deal with any type conversion questions. (For example, you write switch(new Box(b)) { case Box(0) -> … } where b is a byte and 0 is an integer constant…)
So, it’s on our radar :-)
Gavin
</pre>
<blockquote type="cite">
<pre>On 2 Nov 2023, at 11:13, Sebastian Fischer <a href="mailto:mail@sebfisch.de" target="_blank" moz-do-not-send="true"><mail@sebfisch.de></a> wrote:
Hello.
I would like to improve my understanding of the interaction of two JEPs: Pattern matching for switch and Record patterns.
I am new to this list so might have missed previous discussion about this but could not find what I was looking for in the archives.
JEP 441 shows the following grammar for switch labels.
SwitchLabel:
case CaseConstant { , CaseConstant }
case null [, default]
case Pattern [ Guard ]
default
JEP 440 shows the following grammar for patterns.
Pattern:
TypePattern
RecordPattern
TypePattern:
LocalVariableDeclaration
RecordPattern:
ReferenceType ( [ PatternList ] )
PatternList :
Pattern { , Pattern }
As a consequence it is not possible to have case constants in the pattern list of a record pattern. For example consider the following definitions modeling (a simplified version of) boolean expressions.
sealed interface BoolExpr {
enum Constant implements BoolExpr { TRUE, FALSE }
record And(BoolExpr left, BoolExpr right) implements BoolExpr {}
default BoolExpr recursively(UnaryOperator<BoolExpr> transform) {
return transform.apply(switch (this) {
case Constant c -> c;
case And(var left, var right) -> new And(
left.recursively(transform),
right.recursively(transform)
);
});
}
default BoolExpr shortCircuit() {
return recursively(expr -> switch (expr) {
case And(var left, var unused)
when left == Constant.FALSE -> Constant.FALSE;
default ->
expr;
});
}
}
In the definition of `shortCircuit` (which does partial evaluation) we need to use a guard to check if the left argument of `And` is false.
Instead of using an enum, we can model constants as empty records as follows.
sealed interface Constant extends BoolExpr permits True, False {}
record True() implements Constant {}
record False() implements Constant {}
Now we can write `shortCircuit` using a nested record pattern.
default BoolExpr shortCircuit() {
return recursively(expr -> switch (expr) {
case And(False(), var unused) -> new False();
default -> expr;
});
}
It would be convenient to be able to use a nested pattern instead of a guard with the original definition using an enum for constants. Here is a hypothetical implementation of `shortCircuit` that is currently not supported.
default BoolExpr shortCircuit() {
return recursively(expr -> switch (expr) {
case And(Constant.FALSE, var unused) -> Constant.FALSE;
default -> expr;
});
}
What are potential problems with allowing case constants as nested patterns?
Kind regards,
Sebastian
</pre>
</blockquote>
</blockquote>
<br>
</div>
</blockquote>
</div>
</blockquote>
<br>
</body>
</html>