JEP 430 String Templates, some weird scenarios feedback

Brian Goetz brian.goetz at oracle.com
Sat Jun 17 13:40:46 UTC 2023



On 6/17/2023 6:02 AM, Stephen Colebourne wrote:
> On Sat, 17 Jun 2023 at 01:03, Brian Goetz <brian.goetz at oracle.com> wrote:
>> More generally, any variable that is today used in string concat, String::format, or println is a candidate for use in a template.  Many, many of these will not be effectively final.
> OK the logging example is reasonable. And the OP used `interpolate()`
> directly which is non-standard. Maybe the messaging needs to be that
> holding onto an instance of the template is dubious outside of
> frameworks?

I don't think it is dubious, you just have to understand what you have 
in your hands.

For example, if I did:

     int x = 2;
     StringBuilder sb = new StringBuilder().append("Hi ").append(x);
     x = 3;

No one would be surprised in the least that when we eventually call 
toSTring on the StringBuilder, that we captured the value 2 rather than 
the variable x.  The same if we had done list.add(x); this puts the 
value of x in the list.  People understand this.

The RAW processor is kind of the oddball here, in that it returns its 
template argument (the carrier for string framgements and values) 
unprocessed, so it can then be used later (or not, or multiple times) to 
build with an as-yet-unspecified processor. While I get that people 
could think "this is like a lambda", it's not; it's more like a (highly 
structured) method call that returns a builder-like object.  We just 
have to help people connect to the mental model they already have.  
Suggestions for doing so are welcome.

> Having an accessible template implies you can do something
> useful with it, when really the best use for it is to pass to a
> framework-level method..

Running a processor on it *is* useful!  You get to package up the 
template and decide later if, and how, to process it.

> Having reviewed it more, I think my real issue here is different - the
> "template" terminology is very misleading to me. IMO it is NOT a
> template at all, as everything is captured once. A template is a
> "thing with holes", where you fill in the holes before final use.

The trouble with words is that they can have multiple meanings, and 
different people can have different beliefs about which is the "real" 
meaning.  Yes, *one* of the meanings is the "thing with holes", like 
those green flowchart templates IBM gave away for free in the 70s.  
These are interesting because no matter how many times you use it to 
make a square on the paper, the template thingie is unmodified.  We 
might call these "immutable templates" or "factory templates".

But another meaning is *a thing to be filled in*, like a Mad Libs. This 
is often a one-time  thing -- we don't erase a Mad Libs sheet and play 
it again.  (Well, some people might, but it's pretty clearly intended as 
a one-shot thing.)  And we also sometimes call the filled-in thing a 
template, as in "Fill out the Complaint Template and put it in the round 
file".

(So in your above paragraph, you get it right the first three times, by 
saying "to me" and "IMO", but then in the end you come around to saying 
"A template *is*", which you follow up with:

> The API design seems to have two concepts smooshed together - a proper
> template, and a "bound template".

where you reserve "proper" for "the association that comes most readily 
to Stephen's mind".  Would have been better to call them "unbound" and 
"bound" templates, since this is supposedly a discussion about "what 
does template mean to people" and not a "Stephen Imposes His World View" 
discussion.)

But yes, the meaning of template we are using is the bound form, like a 
completed Mad Lib.  The RHS of a template expression (the stringy thing 
with embedded values) is the completed Mad Lib.  The processor takes the 
completed Mad Lib and does something with it, such as reading it to the 
crowd.  The RAW processor saves it for later, perhaps awaiting a more 
suitable audience.

At root, I think what you're saying is "I think BoundTemplate or 
FilledInTemplate or TemplateWithValues might be a better name than 
StringTemplate", which is a totally reasonable opinion!  There's also a 
valid opinion about whether RAW is the right name for the processor that 
yields a StringTemplate; other candidates include LAZY or DEFER or QUOTED.

In the current feature, the type StringTemplate serves two (well, maybe 
1.5) uses.  In the "usual" case (e.g., STR."Hello \{foo}"), a 
StringTemplate is created and passed to the STR processor (invisible to 
the user code); the RAW processor helps that to "escape" back into the 
user code, where it can be used later.  I think this is probably the 
most confusing thing about it; mostly its an internal entity for 
consumption by the processor, but soemtimes we want to let it escape 
into our program.

>   // alternative API design - StringTemplate only contains the fragments

Unfortunately this is not just an alternate API design; it's an 
alternate language design, because (among other reasons) \{} is not 
allowed in string literals today.  The \ can only be used with the 
defined set of escape characters such as \t.

> Reading the Javadoc, it is unclear why `interpolate()` exists. The
> `process()` method appears to be the main standard entry point which
> safely produces the expected outcome. The Javadoc could be read to
> imply that `interpolate()` just joins the fragments and values
> together into a String without validation. Even if it is validated, it
> seems odd to offer a way of producing a String if the natural type of
> the template is not a String.

It exists to serve toString() - like use cases, when you want to take an 
unprocessed template and describe it without processing it. Better names 
and/or descriptions are probably possible.  Perhaps there is a better name.


So, what I take away from this discussion is that you'd like to consider 
some other names for StringTemplate and/or RAW and maybe interpolate?






More information about the amber-dev mailing list