Reconstruction expressions questions

Brian Goetz brian.goetz at oracle.com
Tue Jun 14 18:51:19 UTC 2022


> Pattern overload selection seems overly complex and restrictive for a 
> limited use-case.
>  - It's "magic", bringing new names into context as they are 
> requested, so long as they match. This on its own is probably fine, 
> but it does create (IMO unnecessary) complications around assigning to 
> other local variables and using undeclared variables (can usages 
> affect overloading?).
>  - There's no proper way to choose any particular overload without 
> redundant `x = x;` assignments.
>  - It might not work for a private-representation use-case if you only 
> modify variables shared with public representation & the private one 
> is not "maximal", but want to ensure the internal representation stays 
> the same for whatever reason.
>  - Access control-based selection might help, but that would stray 
> even further from regular overload selection ("it's only used when 
> private?"), and at that point, why not just use access control instead 
> of overloads at all?

This isn't actually about pattern overload selection -- that's defined 
largely as the dual of method overload selection.  What you're asking 
about is how reconstruction expressions would select their patterns.  
(This is probably just a terminology blip.)

I think you might be placing a little too much authority in the 
reconstruction writeup, though.  That's a sketch, whose purpose is (a) 
to explain a possible direction and its underpinnings and (b) provide a 
strawman argument than the end-to-end issues can be addressed.  We put 
these out early to get high-level feedback on the direction and 
concept.  That said, I also think answers to several of the above 
questions are implicit in the model described (e.g., there's no case 
where a redundant `x=x` would make a difference in selection, given the 
requirements for disjoint chains and selecting the maximal ctor/dtor of 
the (sole) chain that is matched.  The only case where this gets weird 
is if there are no assignments at all, in which case it might match 
multiple chains.)

I think what you're questioning is, essentially, "is this the optimal 
tradeoff between simplicity and specificity?"  And that's a fair 
question -- and one we'll take up when we start to design reconstruction 
for arbitrary classes.  The one that gets written up first is usually 
the first credible design, but often it can be simplified further.  The 
good news is that for records, many of the answers are already chosen 
for us.

> My simplest solution would be to only allow one public byname 
> deconstructor and one private, and use the private one when 
> accessible/when using `with-private` or something.

We did pass through the "only one" point in the initial design 
exploration, but this quickly felt unstable.  And having a separate 
feature to select the private one (and, what about other forms of access 
control?) is not a simplifying move.  But these can all be more 
carefully evaluated when we get closer.

>  - Would it make sense to be able to `yield` from a `with` block to 
> skip the rest of the block and finish evaluation?

This feels like mixing two different things.  The block is a transform 
on the state, not an expression on its own.

>  - Would it make sense to (at some point) have `with` for arrays? Say, 
> `x with { [0] = 1; }`? Given array patterns, it would complete the 
> circle of "breaking down and putting back together with identical 
> syntax" (yes that's not the proper wording but it's the general idea).

That would certainly be nice, but it falls afoul of an existing 
simplifying move which is "the block is just an ordinary block of Java 
code."  Introducing a restricted form of assignment statement or 
lvalue-expression is a pretty significant departure.





More information about the amber-dev mailing list