Are templated string embedded expressions "method parameters" or "lambdas"?
forax at univ-mlv.fr
forax at univ-mlv.fr
Fri Oct 29 18:18:39 UTC 2021
----- Original Message -----
> From: "Brian Goetz" <brian.goetz at oracle.com>
> To: "Remi Forax" <forax at univ-mlv.fr>, "Jim Laskey" <james.laskey at oracle.com>
> Cc: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Sent: Vendredi 29 Octobre 2021 19:20:20
> Subject: Re: Are templated string embedded expressions "method parameters" or "lambdas"?
>> For me, "deferred execution" is not the right way to think about the
>> sub expressions of a templated string.
>
> I think there really are two (related) cases here.
>
> The first (and more common) case is when you provide a formatter object
> directly:
>
> Foo f = F."Hello \{name()}"
>
> Here, there are several interesting constraints:
>
> - The template is formatted exactly once, consuming each parameter
> expression exactly once (*)
> - The timing of consuming the parameter expressions is the same as the
> timing of formatting
>
> Under these constraints, the eager-vs-lazy interpretation doesn't really
> matter, because there's no difference in the timing or arity of
> expression evaluation.
>
> The second case is when you are capturing an "unprocessed" template for
> later use:
>
> TemplatedString ts = "Hello \{name()}";
>
> Now, there's no guarantee as to whether the template will be processed
> at all, or once, or more than once. Again, this only makes a difference
> if (a) the expressions have side-effects or (b) the expressions are
> "stateful", acting on state that might have changed since capture time,
> such as static state, current time, etc. (Which sounds very much like
> the things that Streams tells you not to do in behavioral parameters.)
> The sad thing is we would rather people not do these things at all, in
> which case it makes less of a difference.
Do we really need to support the second case at all ?
Instead of
"Hello \{name()}"
it can be written to something like
() -> F."Hello \{name()}"
piggy backing on the semantics of lambdas instead of inventing a new kind of "lambda but not exactly a lambda" thing.
>
> Treating expressions as lazy offers real performance benefits for the
> case where the template will not be processed at all (as in logging
> frameworks); it minimizes the cost of capturing the TS. Treating
> expressions as eager is simpler to reason about (though, in the absence
> of side effects, doesn't really matter), but creates a two-stage
> evaluation where the expressions are evaluated at one point and combined
> at another. Performance is a side-effect too.
I think the choice between eager and lazy should be reflected in the syntax,
if a sub-expression should be evaluated lazily, the expression can be a lambda or a method reference, like
GENERATOR."Hello \(Employee::name)"
regards,
Rémi
>
>
>
> *It may not actually be the case that all are consumed exactly once.
> Imagine a framework where you can specifiy localized messages in a way
> that lets them reorder / reuse parameters; its possible some parameters
> need not be evaluated at all. Again, lazy evaluation defers the costs
> until they are needed.
More information about the amber-spec-experts
mailing list