String Templates Question - are expressions within a TemplateString literal evaluated immediately, or when a template is applied?
Brian Goetz
brian.goetz at oracle.com
Thu Sep 22 19:13:35 UTC 2022
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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20220922/ce390b02/attachment-0001.htm>
More information about the amber-dev
mailing list