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