Is your intent that a string interpolation literal would have a type other than 
String? If so, I agree that this is a third option—with the consequence that 
each API designer now needs to contemplate three-way overloading.

If that is not your intent, then I am not seeing how the prefix helps—so please 
explain?

Thanks,
Guy

On Mar 14, 2024, at 6:00 PM, Maurizio Cimadamore 
<[email protected]> wrote:



On 14/03/2024 19:39, Guy Steele wrote:
This is a very important example to consider. I observe, however, that there 
are at least two possible ways to avoid the unpleasant surprise:

(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.

(2) Don’t overload methods so as to accept either a string or a string template.

I agree with your analysis, but note that there is also a third option:

(3) make it so that both string interpolation literal and string template 
literal have a prefix.

I believe that is enough to solve the issue (because the program I wrote would 
no longer compile: the compiler would require an explicit prefix).

Maurizio

If we were to take approach (2), then:

(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.

(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.

(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

String.format("Hello, my name is %s{name}"); // can you spot the bug?


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`.

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.

—Guy

On Mar 14, 2024, at 1:40 PM, Maurizio Cimadamore 
<[email protected]><mailto:[email protected]> wrote:


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.

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 cheaper (to type) than the safer template 
alternative. This is a bit of a red herring, I think.

The second problem is that interpolation literals can sometimes be deceiving. 
Consider this example:

String.format("Hello, my name is %s{name}"); // can you spot the bug?


Where String::format has a new overload which accepts a StringTemplate.

Basically, since here we forgot the leading “$” (or whatever char that is), the 
whole thing is just a big interpolation. Semantically equivalent to:

 String.format("Hello, my name is %s" + name); // whoops!


This will fail, as String::format will be waiting for an argument (a string), 
but none is provided. So:

|  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)


This is a very odd (and new!) failure mode, that I’m sure is gonna surprise 
developers.

Maurizio

On 14/03/2024 15:08, Guy Steele wrote:



Second thoughts about how to explain a string interpolation literal:



On Mar 13, 2024, at 2:02 PM, Guy Steele 
<[email protected]><mailto:[email protected]> 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}”)`
—————————


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




​


Reply via email to