Looking ahead: pattern assignment
Remi Forax
forax at univ-mlv.fr
Fri Mar 12 22:14:42 UTC 2021
> De: "Alan Malloy" <amalloy at google.com>
> À: "Brian Goetz" <brian.goetz at oracle.com>
> Cc: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Envoyé: Vendredi 12 Mars 2021 22:58:44
> Objet: Re: Looking ahead: pattern assignment
> try-with-resources is a little more subtle than the other contexts. Suppose that
> I write:
> try (Foo(Bar x) = ...) {
> ...
> }
> What should be closed in the finally? The variable x that we bound to, or the
> Foo that contained it?
The instance of Foo, not the instance of Bar.
> Both answers seem a little weird to me. Might it be better not to allow patterns
> in this context ?
It can be handy if we have a pattern method that decomposes the Closeable, by example we have a pattern method HttpRequest.parse() that returns the header and the content of the HTTP request
try (HttpRequest.parse(var header, var content) = getAHttpRequestFrom(...)) {
...
}
regards,
Rémi
> On Fri, Mar 12, 2021 at 12:41 PM Brian Goetz < [ mailto:brian.goetz at oracle.com |
> brian.goetz at oracle.com ] > wrote:
>> While this is not on the immediate horizon, I think we are ready to put the
>> pieces together for pattern assignment. I think we now understand the form this
>> has to take, and the constraints around it.
>> Just as we were successfully able to unify pattern variables with locals*, I
>> would like to be able to unify pattern assignment with assignment.
>> A pattern assignment takes the form:
>> P = e
>> where P is a pattern with at least one binding variable that is total (perhaps
>> with remainder) on the type of e. (If P has some remainder on the type of e,
>> then the assignment will throw NPE or ICCE.) All bindings in P are in scope and
>> DA for the remainder of the block in which P appears, just as with local
>> variable declaration.
>> Pattern assignment should work in all of the following contexts:
>> - Assignment statements: P = e
>> - foreach-loops: for (P : e) { ... }
>> - (optional) try-with-resources: try (P = e) { ... }
>> - (optional) method formals: void m(Point(var x, var y) p) { ... }
>> - (optional) lambda formals: (Point(var x, var y) p) -> { ... }
>> (And I'm sure I forgot some.)
>> Minimally, we have to align the semantics of local variable declaration with
>> assignment with that of pattern matching; `T t = e` should have the same
>> semantics whether we view it as a local declaration plus assignment, or a
>> pattern match. This means that we have to, minimally, align the
>> assignment-context conversions in JLS 5. (If we wish to support patterns in
>> method/lambda formals, we also have to align the method-invocation context
>> conversions.)
>> Early in the game, we explored supporting partial patterns in pattern
>> assignment, such as:
>> let P = e
>> else { ... }
>> where the `else` clause must either complete abruptly, or assign to all bindings
>> declared in `P`. (It wasn't until we unified pattern variables with locals that
>> there was an obvious way to specify the latter.) While this construct is sound,
>> it is in tension with other uses of pattern assignment:
>> - (syntactic) Its pretty hard to imagine an `else` clause without introducing
>> the assignment with some sort of keyword, such as `let`, but this limits its
>> usefulness in other contexts such as method parameter declarations;
>> - (pragmatic) It just doesn't add very much value; if the else throws, it is no
>> less verbose than an if-else.
>> The remaining case where this construct helps is when we want to assign default
>> values:
>> let Point(var x, var y) = aPoint
>> else { x = y = 0; }
>> // can use x, y here either way
>> But, I think we can get there another way, by letting patterns bind to existing
>> variables somehow (we want something like this for the analogue of
>> super-delegation and similar in pattern declarations anyway.) I won't paint
>> that bikeshed here, except to suggest that the let-else construct seems to be a
>> losing price-performance proposition.
>> I suspect the right time to formalize pattern assignment is when we formalize
>> deconstructor declarations (probably next round). In the meantime, we should:
>> - gather a complete list of contexts where pattern assignment makes sense;
>> - nail down semantics of primitive type patterns (see earlier mail);
>> - think about how to align the conversion rules in JLS 5 to align with existing
>> usage.
>> *the only remaining difference between pattern variables and locals is that
>> pattern variables have a more interestingly-shaped scope (and perhaps in the
>> future, pattern variables may have multiple declaration points in the presence
>> of OR patterns / merging via ORing of boolean expressions)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20210312/36d2e797/attachment.htm>
More information about the amber-spec-experts
mailing list