New candidate JEP: 430: String Templates (Preview)

Brian Goetz brian.goetz at oracle.com
Thu Sep 22 18:21:35 UTC 2022


It's a good intuition that there is a  connection here to function 
application, and it is not lost on us that some people really, really 
want to be able to take an instance of a functional interface and apply 
it without having to utter the method name.  Your proposed approach 
holds out the promise of killing two birds with one stone, but it comes 
laden with a strong assumption of where you want to go with function 
application.  (Full disclosure: I don't find the "pretend a functional 
interface is a function" feature very compelling, the benefit is mostly 
"code golf", and it has the negative effect of obscuring what f is.)

But, let's explore the connection separate from that.  It would be a 
valid argument to say that TemplateProcessor is a SAM type, so we don't 
need a special syntax at all, we could just say

     STR.apply("Hello \{name}")

and this would say exactly what it means: construct a TemplatedString, 
and apply the STR processor to it.  What do you think people would say 
about this?  I don't think this would be popular, because people don't 
*want* to think about "construct a templated string, then apply a 
processor" -- they want to think of it as *interpret the templated 
string relative to the processor*.  (A lot of the time, they don't want 
to think about the processor at all, but that's a separate argument.)  
The intermediate templated string is not an artifact that most users 
want to reason about, so we'd rather not shove it in their face.

I think the same applies to a contracted form like `STR.("Hello 
\{name}")`; it encourages the user to think about the templated string 
as a separate value with its own type.  I don't think that improves the 
situation much; it may be five fewer characters, but it is still 
conceptually the same thing.

There's a reason the language has a special syntactic form for string 
literals, rather than making strings by passing arrays of characters to 
a constructor, and there's a reason people have been clamoring for 
"string interpolation" for a long time, even though there exist 
templating libraries that can do the same thing.  We've chosen a point 
on the spectrum that offers more abstractive power than mere 
interpolation, but the syntax was chosen based on balancing how we think 
the users want to think about this, with ensuring that users have to 
make an explicit choice about how to process the template.  It is a fair 
question to ask whether a "special purpose" syntax like this carries its 
weight, but our bet is that Java developers would rather think of string 
processing as something special, even if it is "just applying a function."





On 9/22/2022 1:32 PM, Steve Barham wrote:
>> On 20 Sep 2022, at 19:10, Mark Reinhold<mark.reinhold at oracle.com>  wrote:
>>
>> https://openjdk.org/jeps/430
> Really looking forward to this feature, and would echo the feedback about using \{ } to delimit expressions being a great way to disambiguate template strings from strings proper.
>
> One question I have is around the generality of the JLS change required to handle processors and templates.
>
> Application of a template processor feels an awful lot like application of a Function<>; the call effectively has type Function<TemplateProcessor, TemplatedString, R> which for the specific types of TemplateProcessor and TemplatedString are blessed by the language, such that they support invocation via a dot operator.
>
> If in the future we have language support for application of Function<> interfaces (and associated overloads / parameterisations, ye even unto Function22), is the thinking that it would use a similar mechanism - i.e. STR.”Hello \{name}” is revealed to have been STR.apply(“Hello \{name}”) all along?
>
> If so, it feels like there might be an uneasy difference between 1-ary and n-ary parameter lists, in which we could have STR.”Hello \{name}”, but would need foo.(10, “bar”) for application with multiple parameters.
>
> Handling application via brackets rather than dot (or via dot _and_ brackets) would seem to tidy things up a bit - we still have a special case for the moment in which TemplateProcessor can be invoked with a TemplatedString, it just looks like STR(“Hello \{name}”) or STR.(“Hello \{name}”), but has the benefit of leaving the application syntax open later for the more general case of n-ary application.
>
> Cheers,
>
> Steve
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20220922/5e28a25d/attachment-0001.htm>


More information about the amber-dev mailing list