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