Now that Maurizio has made quite clear the need for string templates to be 
understood as something distinct from strings, when used for security-related 
purposes (the need to ensure that material from interpolated expressions is 
vetted by the template processor), I agree that 2b is undesirable. We do not 
want to tempt users to think that

“Hello, \{x}”

and

“Hello “ + x

are completely interchangeable.

On the other hand, there are applications where vetting is not important, and 
while the rest of this sentence is explicitly stated as a non-goal of JEP 459, 
I suspect we do, secretly, actually want users to feel free to use templates 
rather than “+” concatenation to construct "plain old unvetted strings”. In the 
current state of JEP 459, this can be indicated in a clear way:

STR.”Hello, \{x}”

And of course STR can be replaced by the name of some other template processor.

Brian has now proposed that the template processor mechanism is clunky and 
redundant, and would be better handled by just providing methods that take 
arguments of type StringTemplate. Sounds good to me. In that world, we would 
probably want a template processor method that takes a StringTemplate and just 
does obvious, unvetted string concatenation after doing `toString` on each of 
the expression values. An obvious name for this method is `String.of`. So we 
would write

String.of(”Hello, \{x}”)

But this is unsatisfying because it is verbose.

I suggest that, rather than having a bit of prefix syntax that allows 
specification of any template processor, all we really need is a very concise 
prefix syntax that distinguishes the STR case from all other cases, the 
assumption being that all other cases do vetting of some sort (else they would 
just accept strings rather than string templates). That, plus Archie’s recent 
suggestion that “$” be optional, leads me to suggest the following approach 
(which I suspect might be a good compromise because I expect that nearly 
everyone in this discussion will dislike some aspect of it :-) :

—————————
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}”)`
—————————

Thus you always need “$” to be present before the leading double quote to get a 
template value. If there is no “$” before the leading double quote, you get a 
string value. String literals are constant expressions, but if what otherwise 
looks like a string literal (no leading “$”) contains “\{“, then it is not a 
constant expression (and if having a constant expression is important to some 
user, that user should use “+” concatenation instead). We would need to think 
of a good name for "what otherwise looks like a string literal (no leading “$”) 
but contains ‘\{‘ “; right now, the best I can think of is “string 
interpolation literal”—but it isn't really a literal, it’s an expression. Maybe 
the right terms are:

$”foo”              trivial string template expression
“foo”                string literal
        $”Hello, \{x}”     nontrivial string template expression
        “Hello, \{x}”      string interpolation expression

APIs that need to vet things can provide methods that accept string templates 
but no methods that accept strings; type checking will then prevent the 
accident of writing

SQL.process(“INSERT INTO Students (name) VALUES (\{new name});”);

when it should have been

SQL.process($“INSERT INTO Students (name) VALUES (\{new name});”);

(This example is of course borrowed from the explanation of “Little Bobby 
Tables” over at the Explain XKCD wiki 
https://www.explainxkcd.com/wiki/index.php/Robert%27);_DROP_TABLE_Students;-- .)



On Mar 13, 2024, at 11:45 AM, Maurizio Cimadamore 
<[email protected]> wrote:

Hi Guy,

On 12/03/2024 17:54, Guy Steele wrote:
(1) avoids this problem by making the syntaxes different. (2b) avoids the 
problem by making the semantics match. But (2a) totally has this problem.

I agree that 2a leaves us in a place that is suboptimal.

I think 2b is also undesirable (as I explained elsewhere), as it would 
compromise the design goals of the feature too much IMHO.

So, the choice is (also IMHO) between an ad-hoc conversion (with the problems 
that I described in my previous email) and a different literal syntax (your 
(1)).

Maurizio


Reply via email to