Are templated string embedded expressions "method parameters" or "lambdas"?

Brian Goetz brian.goetz at oracle.com
Sat Oct 30 17:04:46 UTC 2021


> I think that deferred semantics could be confusing and it provides too
> little benefit to justify its use. For example:
>
> DebugLogger."The number of objects: \{counter.incrementAndGet()}";
>
> We saw a number of bugs like this in assert statements. The unpleasant
> thing is that in unit-tests assertions are usually turned on. It's
> possible that debug logging is also turned on for tests. So we can
> have successful tests and buggy production.
>
> Also, it's unclear whether the template processor can invoke the
> embedded expression several times, pass the MethodHandle to another
> thread, invoke two embedded expressions concurrently. It's likely that
> it can. In this case, the results could be totally unpredictable.
>
> Another problem is the IDE refactoring. Taking the example above, we
> cannot extract the variable without changing the semantics:
>
> var count = counter.incrementAndGet();
> DebugLogger."The number of objects: \{count}";
>
> As static analysis is somewhat limited, IDE cannot always predict
> whether the given template processor always executes the embedded
> expression and whether the embedded expression has a side effect.
> Thus, IDE cannot guarantee refactoring safety.

I'd characterize these argument as "this deferral is too magic and 
raises too many questions for too little benefit; if you want deferral, 
do it explicitly with ->.

> Finally, the inability to use non-effectively-final variables would be
> very limiting. Note that the most classic way to iterate numbers in
> Java is still for loop:
>
> for(int i=0; i<array.length; i++) {
>    System.out.println("array[\{i}] = \{array[i]}");
> }
>
> Inability to do this simple thing would be frustrating.

I see this as more a deficiency of loop induction variables than lambdas 
/ other capturing constructs.  For the old-school for-loop, we're kind 
of hosed because the induction variable is intrinsically mutable, but 
for the foreach loop, this is probably fixable;

     for (T x : source)

could treat x as being freshly declared in each block iteration.  We 
visited this during Lambda; perhaps this could be revisited.  So I'm not 
yet convinced that the effectively-final restriction is unreasonable.  
And, we can always relax from there, but can't go stricter.




More information about the amber-spec-experts mailing list