----- Original Message -----
> From: "Brian Goetz" <brian.go...@oracle.com>
> To: "Remi Forax" <fo...@univ-mlv.fr>, "Jim Laskey" <james.las...@oracle.com>
> Cc: "amber-spec-experts" <amber-spec-experts@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.

Reply via email to