<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
This is a very important example to consider. I observe, however, that there are at least two possible ways to avoid the unpleasant surprise:
<div><br>
</div>
<div>(1) Don't have string interpolation literals, because accidentally using a string interpolation literal instead of a string template literals can result in invoking the wrong overload of a method.</div>
<div>
<div><br>
</div>
<div>(2) Don’t overload methods so as to accept either a string or a string template.</div>
<div><br>
</div>
<div>If we were to take approach (2), then:</div>
<div><br>
</div>
<div>(a) We would keep `println` as is, and not allow it to accept a template, but that’s okay—if you thought you wanted a template, what you really want is plan old string interpolation, and the type checking will make sure you don't use the wrong one.</div>
<div><br>
</div>
<div>
<div>(b) A SQL processor would accept a template but not a string—if you thought you wanted string interpolation, what you really want is a template, and the type checking will make sure you don't use the wrong one.</div>
<div><br>
</div>
<div>(c) I think `format` is a special case that we tend to get hung up on, and I think that, in this particular branch of the design space we are exploring, perhaps a name other than `String.format` should be chosen for the method that does string formatting
on templates. Possible names are `StringTemplate.format` and `String.format$`, but I will leave further bikeshedding on this to others. I do recognize that this move will not enable the type system per se to absolutely prevent programmers from writing</div>
<div class="markdown-here-wrapper" data-md-url="">
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 1em; line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; background-color: rgb(248, 248, 248); 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?<br></code></pre>
</div>
<div>but, as Clement has observed, such cases will probably provoke a warning about a mismatch between the number of arguments and the number of %-specifiers that require parameters, so maybe overloading would be okay anyway for `String.format`.</div>
</div>
<div><br>
</div>
<div>Anyway, my point is that whether to overload a method to accept either a string or a string template can be evaluated on a case-by-case basis according to a small number of principles that I think we could enumerate and explain pretty easily.</div>
<div><br>
</div>
<div>—Guy</div>
<div>
<div><br>
<blockquote type="cite">
<div>On Mar 14, 2024, at 1:40 PM, Maurizio Cimadamore <maurizio.cimadamore@oracle.com> wrote:</div>
<br class="Apple-interchange-newline">
<div>
<div>
<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>
<div style="margin: 0px 0px 1.2em !important;"><br class="webkit-block-placeholder">
</div>
<div class="markdown-here-exclude">
<div><br class="webkit-block-placeholder">
</div>
<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>
<div><br class="webkit-block-placeholder">
</div>
</div>
<div style="margin: 0px 0px 1.2em !important;"><br class="webkit-block-placeholder">
</div>
<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>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>
</body>
</html>