Feedback on Member Patterns syntax
Loïc Bertrand
loic.brtd at gmail.com
Sat Apr 20 18:11:02 UTC 2024
Dear Amber Expert Group,
I'd like to share with you some feedback on the syntax of member patterns.
Please tell me if I make any wrong assumptions.
I'd prefer the generic type parameters (`<T>`) to be on the right hand side
of
the `pattern` keyword to have all the keywords on the same side, and the
types
on the other side. I like the familiarity of declaring a pattern almost
like we
declare a method :
```
public static pattern <T> Optional<T> of(T t) {
if (that.isPresent()) {
match(that.get());
}
}
```
I like the `match` keyword for explicitly indicating a match success. The
language already has "callable" keywords such as `this()` and `super()`. It
also works when there's no match variable to extract :
```
public static pattern <T> Optional<T> empty() {
if (that.isEmpty()) {
match();
}
}
```
For a moment I thought it could also be useful to be allowed to use it
inside a
lambda expression :
```
public static pattern <T> Optional<T> of(T t) {
that.ifPresent(value -> match(value))
// or "match-reference" ? Maybe not that useful.
that.ifPresent(::match);
}
```
But I'm not sure what should happen if such a lambda expression is called
at a
later point, when the body of the pattern member has already finished
executing.
Maybe seeing the `match` keyword as a kind of `return` is simpler.
I wouldn't allow using any other name than `that` for the match candidate,
just
like `this` cannot be renamed. I also wouldn't explicitly declare the `that`
variable in most cases. If really necessary, it could be added at the
beginning
of the "parameter" list, just like the `this` keyword can be added at the
beginning of the parameter list of an instance method (to put annotations
on it,
for example) :
```
public static pattern <T> Optional<T> of(@NonNull Optional<T> that, T t) {
...
}
```
The functional `match` keyword seems more concise than assigning each
variable,
it avoids repeating each "parameter" name 3 times (in opposition to the
good-old
constructor ceremony of `(int x, int y) { this.x = x; this.y = y; }`). It
also
reinforces the positional (vs named) nature of pattern matched variables :
```
class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public pattern Point(int x, int y) {
match(that.x, that.y);
}
}
// Here, x and y are not extracted by name but by position if I'm not
mistaken
if (p instanceof Point(int x, int y)) {
...
}
```
One question I have in mind is the following : should the pattern
"parameter"
names be part of the API/class-file if we want to be able to use `with`
expressions with non-record classes which define a deconstructor?
```
var p = new Point(5, 8);
var newP = p with { x = 3; };
```
-- Loïc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-comments/attachments/20240420/e2c77e4b/attachment.htm>
More information about the amber-spec-comments
mailing list