Allow case constants as nested patterns?
Sebastian Fischer
mail at sebfisch.de
Thu Nov 2 11:13:50 UTC 2023
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20231102/9f42b6a4/attachment.htm>
More information about the amber-dev
mailing list