String Templates Question - are expressions within a TemplateString literal evaluated immediately, or when a template is applied?
Nathan Walker
nathan.h.walker at gmail.com
Thu Sep 22 19:09:40 UTC 2022
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/3fbb3b99/attachment.htm>
More information about the amber-dev
mailing list