Looking ahead: pattern assignment

Brian Goetz brian.goetz at oracle.com
Fri Mar 19 19:35:15 UTC 2021


>>
>> 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) -> { ... }
>
> It is easy (and normal) here, I think, to be a little confused. At the 
> beginning I was thinking "boy inference of lambdas with target typing 
> AND patterns is gonna make javac cry" - but I think the key to a lot 
> of these is that whenever you see a pattern declaration, it's like if 
> you had an _explicit_ type. So, while there might be magic at runtime 
> to decompose the value into the binding variables, from a static 
> perspective, typing the lambda:
>
> Point(var x, var y) -> distance(x, y)
>
> is no different than typing this:
>
> Point p -> distance(p.x, p.y)
>

Exactly; think of it as a syntactic desugaring

     Point(var x, var y) p -> e

to

     Point p -> { Point(var x, var y) = p; return e; }

My intent was actually to require the top-level variable (p) in 
lambda/method formals, which emphasizes this.

> Crucially, the pattern provides an explicit type (including generic 
> type arguments, at least initially).
>
> From here I guess the next step would be, for a lambda like this:
>
> Box<String>(String s) -> ...
>
> to avoid the outer `<String>` - but I'm not sure about that step. I 
> think if we treat a pattern as a replacement for an explicit type, 
> things works nicely and there's a simple user model to explain. If we 
> make it too magic, it could be more concise, but also more confusing.
>

Agree.

> I was thinking that maybe another way to get at that is by using 
> unchecked exceptions - e.g. if pattern failure raised a well-known 
> unchecked exception, then users could have a chance (if they want) at 
> looking as to why things failed.
>
> try {
>    P p = e;
>    ...
> } catch (...)
>
> The problem with this though is that the handler code is very distant 
> from where the failure has happened (unlike in let/else).
>

Not only that, but if the exception is unchecked, it is really not 
obvious that the match is even partial.  I like that we require an 
intrinsically conditional control flow construct (instanceof, switch, 
catch) for partial patterns, and only allow total patterns in things 
that "look total".

> And we can't really do:
>
> P p;
> try {
>   p = e;
> } catch (...)
>
> Because the proposed pattern assignment doesn't support some form of 
> blank declaration - e.g. a way to say:
>
> Point(int x, int y);
> if (...) {
>     // assign pattern from here
> } else {
>    // assign pattern from here
> }
>
> Is this something we view as a limitation?
>

It's a glass which is either P% full or (100-P)% empty :)  But I would 
much rather drive towards making what you wrote legal, in some way, 
rather than make assignment partial in a less-than-fully-transparent way.

We've already encountered another place where we might want 
bind-to-existing: composition of deconstructors/patterns.  Suppose:

     class A {
         int a;

         deconstructor(int a) { a = this.a; }
     }

     class B extends A {
         int b;

        deconstructor(int a, int b) {
*           super(a);*
            b = this.b;
        }
    }

If we can't invoke another pattern with bind-to-one-of-my-bindings, then 
we'd have to write something like:

        deconstructor(int a, int b) {
            super(var aa) = this;
            a = aa;
            b = this.b;
        }

While this is not the worst thing in the world, it will surely be a 
persistent irritation.   So *some* way to say "bind to this variable" 
possibly under some restrictions (DU?) seems desirable. If we had that, 
then your if-else would do the trick:

     int x, y;  // blank locals, therefore DU
     if (!(target instanceof Point(__my x, __my y)) {
         x = y = 0;
     }




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20210319/0ff3c307/attachment.htm>


More information about the amber-spec-experts mailing list