<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div class="markdown-here-wrapper" data-md-url="" style="">
<p style="margin: 0px 0px 1.2em !important;">Not to pour too much
cold water on the idea of having string interpolation literal,
but I’d like to mention a few points here.</p>
<p style="margin: 0px 0px 1.2em !important;">First, it was a
deliberate design goal of the string template feature to make
interpolation an explicit act. Note that, if we had the syntax
you describe, we actually achieve the opposite effect: string
interpolation is now the default, and implicit, and actually <em>cheaper</em>
(to type) than the safer template alternative. This is a bit of
a red herring, I think.</p>
<p style="margin: 0px 0px 1.2em !important;">The second problem is
that interpolation literals can sometimes be deceiving. Consider
this example:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">String.format("Hello, my name is %s{name}"); // can you spot the bug?
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">Where <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">String::format</code>
has a new overload which accepts a StringTemplate.</p>
<p style="margin: 0px 0px 1.2em !important;">Basically, since here
we forgot the leading “$” (or whatever char that is), the whole
thing is just a big interpolation. Semantically equivalent to:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"> String.format("Hello, my name is %s" + name); // whoops!
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">This will fail, as <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">String::format</code>
will be waiting for an argument (a string), but none is
provided. So:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">| Exception java.util.MissingFormatArgumentException: Format specifier '%s'
| at Formatter.format (Formatter.java:2672)
| at Formatter.format (Formatter.java:2609)
| at String.format (String.java:2897)
| at (#2:1)
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">This is a very odd
(and new!) failure mode, that I’m sure is gonna surprise
developers.</p>
<p style="margin: 0px 0px 1.2em !important;">Maurizio</p>
<p style="margin: 0px 0px 1.2em !important;">On 14/03/2024 15:08,
Guy Steele wrote:</p>
<p style="margin: 0px 0px 1.2em !important;"></p>
<div class="markdown-here-exclude">
<p></p>
<blockquote type="cite" cite="mid:3F8C64A7-BEB8-4BA2-A9B1-E00C14578B28@oracle.com">
<pre class="moz-quote-pre" wrap="">Second thoughts about how to explain a string interpolation literal:
</pre>
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">On Mar 13, 2024, at 2:02 PM, Guy Steele <a class="moz-txt-link-rfc2396E" href="mailto:guy.steele@oracle.com"><guy.steele@oracle.com></a> wrote:
. . .
—————————
String is not a subtype of StringTemplate; they are disjoint types.
$”foo” is a (trivial) string template literal
“foo” is a string literal
$”Hello, \{x}” is a (nontrivial) string template literal
“Hello, \{x}” is a shorthand (expanded by the compiler) for `String.of($“Hello, \{x}”)`
—————————
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">Given that the intent is that String.of (or whatever we want to call it—possibly the `interpolation` instance method of class `StringTemplate` rather than a static method `String.of`) should just do standard string concatenation, we might be better off just saying that a string interpolation literal is expanded by the compiler into uses of “+”; for example,
“Hello, \{x}.”
(I have added a period to the example to make the point clearer) is expanded into
“Hello, “ + x + “.”
and in general
“c0\{e1}c1\{e2}c2…\{en}cn”
(where each ck is a possibly empty sequence of string characters and each ek is an expression) is expanded into
“c0” + (e1) + “c1” + (e2) + “c2” + … + (en) + “cn”
The point is that, with this definition, “c0\{e1}c1\{e2}c2…\{en}cn” is a constant expression iff every ek is a constant expression. This is handy for interpolating constant variables into a string that is itself intended to be constant.
—Guy
</pre>
</blockquote>
<p></p>
</div>
<p style="margin: 0px 0px 1.2em !important;"></p>
<div title="MDH:PHA+Tm90IHRvIHBvdXIgdG9vIG11Y2ggY29sZCB3YXRlciBvbiB0aGUgaWRlYSBvZiBoYXZpbmcg
c3RyaW5nIGludGVycG9sYXRpb24gbGl0ZXJhbCwgYnV0IEknZCBsaWtlIHRvIG1lbnRpb24gYSBm
ZXcgcG9pbnRzIGhlcmUuPC9wPjxwPkZpcnN0LCBpdCB3YXMgYSBkZWxpYmVyYXRlIGRlc2lnbiBn
b2FsIG9mIHRoZSBzdHJpbmcgdGVtcGxhdGUgZmVhdHVyZSB0byBtYWtlIGludGVycG9sYXRpb24g
YW4gZXhwbGljaXQgYWN0LiBOb3RlIHRoYXQsIGlmIHdlIGhhZCB0aGUgc3ludGF4IHlvdSBkZXNj
cmliZSwgd2UgYWN0dWFsbHkgYWNoaWV2ZSB0aGUgb3Bwb3NpdGUgZWZmZWN0OiBzdHJpbmcgaW50
ZXJwb2xhdGlvbiBpcyBub3cgdGhlIGRlZmF1bHQsIGFuZCBpbXBsaWNpdCwgYW5kIGFjdHVhbGx5
IF9jaGVhcGVyXyAodG8gdHlwZSkgdGhhbiB0aGUgc2FmZXIgdGVtcGxhdGUgYWx0ZXJuYXRpdmUu
IFRoaXMgaXMgYSBiaXQgb2YgYSByZWQgaGVycmluZywgSSB0aGluay48L3A+PHA+VGhlIHNlY29u
ZCBwcm9ibGVtIGlzIHRoYXQgaW50ZXJwb2xhdGlvbiBsaXRlcmFscyBjYW4gc29tZXRpbWVzIGJl
IGRlY2VpdmluZy4gQ29uc2lkZXIgdGhpcyBleGFtcGxlOjwvcD48cD5gYGA8YnI+U3RyaW5nLmZv
cm1hdCgiSGVsbG8sIG15IG5hbWUgaXMgJXN7bmFtZX0iKTsgLy8gY2FuIHlvdSBzcG90IHRoZSBi
dWc/PGJyPmBgYDwvcD48cD5XaGVyZSBgU3RyaW5nOjpmb3JtYXRgIGhhcyBhIG5ldyBvdmVybG9h
ZCB3aGljaCBhY2NlcHRzIGEgU3RyaW5nVGVtcGxhdGUuPC9wPjxwPkJhc2ljYWxseSwgc2luY2Ug
aGVyZSB3ZSBmb3Jnb3QgdGhlIGxlYWRpbmcgIiQiIChvciB3aGF0ZXZlciBjaGFyIHRoYXQgaXMp
LCB0aGUgd2hvbGUgdGhpbmcgaXMganVzdCBhIGJpZyBpbnRlcnBvbGF0aW9uLiBTZW1hbnRpY2Fs
bHkgZXF1aXZhbGVudCB0bzo8L3A+PHA+YGBgPGJyPgpTdHJpbmcuZm9ybWF0KCJIZWxsbywgbXkg
bmFtZSBpcyAlcyIgKyBuYW1lKTsgLy8gd2hvb3BzITxicj4KYGBgPC9wPgo8cD5UaGlzIHdpbGwg
ZmFpbCwgYXMgYFN0cmluZzo6Zm9ybWF0YCB3aWxsIGJlIHdhaXRpbmcgZm9yIGFuIGFyZ3VtZW50
IChhIHN0cmluZyksIGJ1dCBub25lIGlzIHByb3ZpZGVkLiBTbzo8L3A+PHA+YGBgPGJyPnwmbmJz
cDsgRXhjZXB0aW9uIGphdmEudXRpbC5NaXNzaW5nRm9ybWF0QXJndW1lbnRFeGNlcHRpb246IEZv
cm1hdCBzcGVjaWZpZXIgJyVzJzxicj58Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i
c3A7Jm5ic3A7IGF0IEZvcm1hdHRlci5mb3JtYXQgKEZvcm1hdHRlci5qYXZhOjI2NzIpPGJyPnwm
bmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgYXQgRm9ybWF0dGVyLmZv
cm1hdCAoRm9ybWF0dGVyLmphdmE6MjYwOSk8YnI+fCZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu
YnNwOyZuYnNwOyZuYnNwOyBhdCBTdHJpbmcuZm9ybWF0IChTdHJpbmcuamF2YToyODk3KTxicj58
Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IGF0ICgjMjoxKTxicj5g
YGA8L3A+PHA+VGhpcyBpcyBhIHZlcnkgb2RkIChhbmQgbmV3ISkgZmFpbHVyZSBtb2RlLCB0aGF0
IEknbSBzdXJlIGlzIGdvbm5hIHN1cnByaXNlIGRldmVsb3BlcnMuPC9wPjxwPk1hdXJpemlvPGJy
PjwvcD48cD48YnI+PC9wPjxwPjwvcD48cD48YnI+PC9wPjxkaXYgY2xhc3M9Im1vei1jaXRlLXBy
ZWZpeCI+T24gMTQvMDMvMjAyNCAxNTowOCwgR3V5IFN0ZWVsZSB3cm90ZTo8YnI+PC9kaXY+PGJs
b2NrcXVvdGUgdHlwZT0iY2l0ZSIgY2l0ZT0ibWlkOjNGOEM2NEE3LUJFQjgtNEJBMi1BOUIxLUUw
MEMxNDU3OEIyOEBvcmFjbGUuY29tIj48cHJlIGNsYXNzPSJtb3otcXVvdGUtcHJlIiB3cmFwPSIi
PlNlY29uZCB0aG91Z2h0cyBhYm91dCBob3cgdG8gZXhwbGFpbiBhIHN0cmluZyBpbnRlcnBvbGF0
aW9uIGxpdGVyYWw6Cgo8L3ByZT48YmxvY2txdW90ZSB0eXBlPSJjaXRlIj48cHJlIGNsYXNzPSJt
b3otcXVvdGUtcHJlIiB3cmFwPSIiPk9uIE1hciAxMywgMjAyNCwgYXQgMjowMuKAr1BNLCBHdXkg
U3RlZWxlICZsdDtndXkuc3RlZWxlQG9yYWNsZS5jb20mZ3Q7IHdyb3RlOgouIC4gLgoK4oCU4oCU
4oCU4oCU4oCU4oCU4oCU4oCU4oCUClN0cmluZyBpcyBub3QgYSBzdWJ0eXBlIG9mIFN0cmluZ1Rl
bXBsYXRlOyB0aGV5IGFyZSBkaXNqb2ludCB0eXBlcy4KCgkk4oCdZm9v4oCdICAgICAgICAgICAg
ICBpcyBhICh0cml2aWFsKSBzdHJpbmcgdGVtcGxhdGUgbGl0ZXJhbAoJ4oCcZm9v4oCdICAgICAg
ICAgICAgICAgIGlzIGEgc3RyaW5nIGxpdGVyYWwKICAgICAgICAk4oCdSGVsbG8sIFx7eH3igJ0g
ICAgIGlzIGEgKG5vbnRyaXZpYWwpIHN0cmluZyB0ZW1wbGF0ZSBsaXRlcmFsCiAgICAgICAg4oCc
SGVsbG8sIFx7eH3igJ0gICAgICBpcyBhIHNob3J0aGFuZCAoZXhwYW5kZWQgYnkgdGhlIGNvbXBp
bGVyKSBmb3IgYFN0cmluZy5vZigk4oCcSGVsbG8sIFx7eH3igJ0pYArigJTigJTigJTigJTigJTi
gJTigJTigJTigJQKPC9wcmU+PC9ibG9ja3F1b3RlPjxwcmUgY2xhc3M9Im1vei1xdW90ZS1wcmUi
IHdyYXA9IiI+CkdpdmVuIHRoYXQgdGhlIGludGVudCBpcyB0aGF0IFN0cmluZy5vZiAob3Igd2hh
dGV2ZXIgd2Ugd2FudCB0byBjYWxsIGl04oCUcG9zc2libHkgdGhlIGBpbnRlcnBvbGF0aW9uYCBp
bnN0YW5jZSBtZXRob2Qgb2YgY2xhc3MgYFN0cmluZ1RlbXBsYXRlYCByYXRoZXIgdGhhbiBhIHN0
YXRpYyBtZXRob2QgYFN0cmluZy5vZmApIHNob3VsZCBqdXN0IGRvIHN0YW5kYXJkIHN0cmluZyBj
b25jYXRlbmF0aW9uLCB3ZSBtaWdodCBiZSBiZXR0ZXIgb2ZmIGp1c3Qgc2F5aW5nIHRoYXQgYSBz
dHJpbmcgaW50ZXJwb2xhdGlvbiBsaXRlcmFsIGlzIGV4cGFuZGVkIGJ5IHRoZSBjb21waWxlciBp
bnRvIHVzZXMgb2Yg4oCcK+KAnTsgZm9yIGV4YW1wbGUsCgogICAgICAgICDigJxIZWxsbywgXHt4
fS7igJ0KCihJIGhhdmUgYWRkZWQgYSBwZXJpb2QgdG8gdGhlIGV4YW1wbGUgdG8gbWFrZSB0aGUg
cG9pbnQgY2xlYXJlcikgaXMgZXhwYW5kZWQgaW50bwoKICAgICAgICDigJxIZWxsbywg4oCcICsg
eCArIOKAnC7igJ0KCmFuZCBpbiBnZW5lcmFsCgogICAgICAgIOKAnGMwXHtlMX1jMVx7ZTJ9YzLi
gKZce2VufWNu4oCdCgood2hlcmUgZWFjaCBjayBpcyBhIHBvc3NpYmx5IGVtcHR5IHNlcXVlbmNl
IG9mIHN0cmluZyBjaGFyYWN0ZXJzIGFuZCBlYWNoIGVrIGlzIGFuIGV4cHJlc3Npb24pICBpcyBl
eHBhbmRlZCBpbnRvCgogICAgICAgIOKAnGMw4oCdICsgKGUxKSArIOKAnGMx4oCdICsgKGUyKSAr
IOKAnGMy4oCdICsg4oCmICsgKGVuKSArIOKAnGNu4oCdCgpUaGUgcG9pbnQgaXMgdGhhdCwgd2l0
aCB0aGlzIGRlZmluaXRpb24sIOKAnGMwXHtlMX1jMVx7ZTJ9YzLigKZce2VufWNu4oCdIGlzIGEg
Y29uc3RhbnQgZXhwcmVzc2lvbiBpZmYgZXZlcnkgZWsgaXMgYSBjb25zdGFudCBleHByZXNzaW9u
LiBUaGlzIGlzIGhhbmR5IGZvciBpbnRlcnBvbGF0aW5nIGNvbnN0YW50IHZhcmlhYmxlcyBpbnRv
IGEgc3RyaW5nIHRoYXQgaXMgaXRzZWxmIGludGVuZGVkIHRvIGJlIGNvbnN0YW50LgoK4oCUR3V5
Cgo8L3ByZT48L2Jsb2NrcXVvdGU+" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0;"></div>
</div>
</body>
</html>