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