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