String Templates Question - are expressions within a TemplateString literal evaluated immediately, or when a template is applied?

Remi Forax forax at univ-mlv.fr
Thu Sep 22 21:25:42 UTC 2022


----- Original Message -----
> From: "Alex Buckley" <alex.buckley at oracle.com>
> To: "John Rose" <john.r.rose at oracle.com>, "Brian Goetz" <brian.goetz at oracle.com>
> Cc: "Nathan Walker" <nathan.h.walker at gmail.com>, "Jim Laskey" <james.laskey at oracle.com>, "amber-dev"
> <amber-dev at openjdk.org>
> Sent: Thursday, September 22, 2022 11:01:37 PM
> Subject: Re: String Templates Question - are expressions within a TemplateString literal evaluated immediately, or when
> a template is applied?

> The JEP also notes that "... it is not possible for a template processor
> to obtain, from a TemplatedString, the exact characters which appear in
> a template in source code; only the values of the embedded expressions
> are available, not the embedded expressions themselves."
> 
> If a future Java platform allows the embedded expressions themselves to
> be represented at run time (e.g. via a dynamically-computed constant
> that denotes the AST seen at compile time), then a template processor
> could choose to (re)evaluate an embedded expression in the current
> environment, no lambda "quoting" needed. A string template expression's
> deference to a template processor during evaluation is most unusual, and
> quite magical.

Usually you still need quoting because you do not know where to draw the line in between where things are values and where things are ASTs.
Otherwise the whole function, the whole class, the whole library/application becomes an AST.

> 
> Alex

R2mi

> 
> On 9/22/2022 1:37 PM, John Rose wrote:
>> Logging is a good use case (but not at all the only one) for this move
>> of “quoting” an expression (for later “unquoting”) with a nullary lambda
>> prefix.
>> 
>> I put a discussion about this topic here:
>> “Java supplier lambda, the Ultimate Quote”
>> http://cr.openjdk.java.net/~jrose/jls/eta-abstraction-expr-quoting.html
>> <http://cr.openjdk.java.net/~jrose/jls/eta-abstraction-expr-quoting.html>
>> 
>> If we had an “auto-quote” feature (see the appendix of the above doc)
>> logger classes could get the delayed execution as part of their API
>> declarations, in the way that Nathan is apparently envisioning. But in
>> practice, adding |()->| before your logger expressions is not a huge
>> burden. Yeah, you’d want to say |LOG."template \{stuff}"| instead of
>> |log(()->STR.”template \{stuff}”)|. But it’s not so terrible as to
>> motivate (all by itself) sugary elision of the |()->| quote.
>> 
>> For my part, I’m really really glad that string templates did not add a
>> hard-coded feature into their design for this sort of expression
>> quoting. I think such a feature deserves to be considered on its own,
>> separately for many kinds of APIs, if at all.
>> 
>> (Idea of the moment: Allow the string template processor |apply| method
>> to accept a |Supplier<ST>|, instead of |ST|. Then push an auto-quote
>> rule into the desugaring of |LOG.<<ST>>|, when |LOG::apply| takes a
>> supplier. This could be added compatibly to the present design, as a
>> future feature. Sort of like some proposals to add new rules for
>> enhanced-for over streams, by adjusting the types around the
>> enhanced-for. String templates could support many, many such compatible
>> additions, IMO, and they should be rolled out in a measured and cautious
>> way, if at all.)
>> 
>> On 22 Sep 2022, at 12:13, Brian Goetz wrote:
>> 
>>     We went around on this a few times, and in the end concluded that it
>>     is easy to just wrap the whole thing with a lambda:
>> 
>>          () -> STR."Connection from \{name} at \{time}"
>> 
>>     which is a Supplier<String>.  Lots of logging frameworks already are
>>     prepared to deal with Supplier.
>> 
>>     On 9/22/2022 3:09 PM, Nathan Walker wrote:
>>>     That was all about what I expected.  And it is probably the option
>>>     that will result in the fewest surprises for developers.  The log
>>>     example you linked was very interesting.
>>>
>>>     Has permitting lambda/method-reference syntax to insert lazy
>>>     expressions been discussed before?  I would really love to be able
>>>     to do something like "The time is \{Instant::now}" or "The time is
>>>     \{()->Instant.now()}"
>>>
>>>     I think there is a lot of potential in allowing TemplateProcessors
>>>     that elect to skip processing a template for some precondition
>>>     avoid the overhead of any expensive embedded expressions, and I
>>>     think this would be especially true in processors that can fail by
>>>     throwing a checked exception.
>>>
>>>     Thanks,
>>>     Nathan
>>>
>>>     On Thu, Sep 22, 2022 at 10:17 AM Jim Laskey
>>>     <james.laskey at oracle.com> wrote:
>>>
>>>
>>>
>>>>         On Sep 22, 2022, at 11:08 AM, Nathan Walker
>>>>         <nathan.h.walker at gmail.com> wrote:
>>>>
>>>>         Hi folks,
>>>>
>>>>         Question regarding TemplateStrings that I could not seem to
>>>>         find the answer to in the JEP write up or the Javadoc for
>>>>         TemplateString:  Is the expression evaluation lazy, or immediate?
>>>>
>>>>         In other words, if I do something like this:
>>>>
>>>>              List<Integer> list=new ArrayList<>();
>>>>              TemplateString ts = "size = \{list.size()}"
>>>>              list.add(1);
>>>>              System.out.println(ts.apply(STR));
>>>>
>>>>         Will it print out size = 0, or size = 1?
>>>
>>>         The expression is evaluated and the value is captured when
>>>         creating the TemplatedString instance. There is some
>>>         discussion around left to right evaluation that tries
>>>         to clarify this. So the answer is “size = 0”.
>>>
>>>
>>>>
>>>>         My main reason for asking is that I would love for string
>>>>         templates to result in logging interfaces with overloaded
>>>>         methods that can take TemplateStrings instead of strings, and
>>>>         which are only evaluated if the log level is enabled.  So
>>>>         that instead of something like this:
>>>>
>>>>              if (logger.isEnabled(Level.DEBUG)) {
>>>>                   logger.log(Level.DEBUG, "Expensive value is " +
>>>>         lookup() );
>>>>              }
>>>>
>>>>         we can just do:
>>>>
>>>>              log.log(Level.DEBUG, "Expensive value is \{lookup()}");
>>>>
>>>>         And be confident that the cost of invoking lookup() will only
>>>>         be paid if DEBUG is enabled.
>>>>
>>>>         Probably over 80% of the string building I have seen over my
>>>>         career has been related to building log messages.  And the
>>>>         mistakes I have most often seen are:
>>>>
>>>>              1. Expensive message construction not guarded by
>>>>         checking if logging is enabled at that level
>>>>              2. Expensive message construction guarded, but by
>>>>         checking the *wrong* logging level (e.g. check INFO, log at
>>>>         ERROR)
>>>>              3. Using some sort of parameterized message/string
>>>>         format but getting the parameters wrong (out of order,
>>>>         missing one, having too many, etc.)
>>>>
>>>>         If TemplateStrings evaluate their expression fragments only
>>>>         when processed then every one of these problems gets
>>>>         addressed, and logging code becomes *a lot* simpler to read,
>>>>         write, and code review.
>>>>
>>>>         (Random side note: I *love* the choice of \ instead of $.  It
>>>>         took some time for me to get use to the idea, but keeping the
>>>>         same escape character is fantastic and I wish more languages
>>>>         had done that instead of using $)
>>>
>>>         You can play some tricks with Suppliers or Futures + lambdas
>>>         to get lazy evaluation. I have an roughed out (i.e., old)
>>>         example at
>>>         https://cr.openjdk.java.net/~jlaskey/templates/examples/Log.java
>>>
>>>         Cheers,
>>>
>>>         — Jim
>>>
>>>
>>>
>>>>
>>>>         Thanks for your time,
>>>>         Nathan
>>>>         --
>>>>         Nathan H. Walker
>>>>         nathan.h.walker at gmail.com
>>>>         (703) 987-8937
>>>>
>>>>
>>>
>>>     --
>>>     Nathan H. Walker
>>>     nathan.h.walker at gmail.com
>>>     (703) 987-8937
>>>
>>>


More information about the amber-dev mailing list