Update on String Templates (JEP 459)

Guy Steele guy.steele at oracle.com
Fri Mar 15 16:07:35 UTC 2024


On Mar 15, 2024, at 5:56 AM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:On 15/03/2024 02:10, Guy Steele wrote:
Oh, I think I get it now; I misinterpreted "The compiler might require a prefix here” to mean "The compiler might require a prefix on a literal that is a method argument”, but I now see, from your later sentence "Basically, requiring all literals that have embedded expression to have a prefix . . .” that maybe you just want to adjust the syntax of literals to be roughly what Clement suggested:

“…”                             plain string literal, cannot contain \{…}, type is String
INTERPOLATION”…”     string interpolation, may contain \{…}, type is String
TEMPLATE”…”      string template, , may contain \{…}, type is StringTemplate

where the precise syntax for the prefixed INTERPOLATION and TEMPLATE is to be determined. Do I understand your proposal correctly now?
Yes, with the further tweak that the prefix (with syntax TBD) might be omitted in the "obvious cases" (but kept for clarity):

* "Hello" w/o prefix is just String
* "Hello \{world}" without prefix is just StringTemplate

Does this help? (I'm basically trying to get to a world where use of prefix will be relatively rare, as common cases have the right defaults).

Yes, this helps immensely.

So in the model you suggest, string templates would mostly not need prefixes, but in the example I raised where one might foresee editing templates so as to cross into or out of the edge case of zero template expressions, I could choose, if I wish, to write

SQL.process(TEMPLATE”CREATE TABLE foo;”);
SQL.process(TEMPLATE”ALTER TABLE foo ADD name varchar(40);”);
SQL.process(TEMPLATE”ALTER TABLE foo ADD title varchar(30);”);
SQL.process(TEMPLATE”INSERT INTO foo (name, title) VALUES (‘Guy’, ‘Hacker’);”);
SQL.process(TEMPLATE”INSERT INTO foo (name, title) VALUES (\{other name}, \{other
job});”);

rather than

SQL.process(”CREATE TABLE foo;”);
SQL.process(”ALTER TABLE foo ADD name varchar(40);”);
SQL.process(”ALTER TABLE foo ADD title varchar(30);”);
SQL.process(”INSERT INTO foo (name, title) VALUES (‘Guy’, ‘Hacker’);”);
SQL.process(TEMPLATE”INSERT INTO foo (name, title) VALUES (\{other name}, \{other
job});”);

That makes sense to me in this two-prefix model.

Then again, now that I ponder the space of use cases, it may be that, despite my initial enthusiasm, having a separate string interpolation syntax may not carry its weight if its uses are relatively rare. We always have the option of using a string template and then applying an interpolation processor (which might be spelled `String.of(<template>)` or `(<template>).interpolate()` or some other way), and about all we lose from that approach is the ability to use string interpolation to specify a constant expression—for which we still have the old-fashioned alternative of using `+` concatenation. If we drop string interpolation, we can then drop the INTERPOLATION prefix, and we are back to a single-prefix model, and the remaining question is whether that prefix is optional, at least in some cases. Okay, I think I now have a better understanding of the relationships among the various proposals in the design space. Thanks for your patience.


And now that I have that better understanding, I think I lean toward (a) abandoning string interpolation and (b) having a single, short, _non-optional_ prefix for templates (“$” would be a plausible choice), on the grounds that I think it makes code more readable if templates are always distinguished up front from strings—and this is especially helpful when the templates are rather long and any `\{` present might be far from the beginning. It has a minimal number of cases to explain:

“…”      string literal, must not contain \{…}, type String
$”…”    template literal, may contain \{…}, type StringTemplate

I think we have all made an honest effort to explain string templates as a simple and clean superset of string literals, but now that we have considered the typing and overloading issues, my opinion is that it just isn’t possible without some amount of unwanted complication. Strings and string templates are just different beasts, and we would do well to maintain that distinction rather than trying to conflate them. Yes, requiring a prefix on templates would impose a small cost—perhaps we should regard it as a "syn-tax" rather than a “cover charge”—on every template we write, but I judge that cost well worth it for the readability it would buy.

(By the way, I appreciate John’s suggestion of allowing a template to begin with  “\{} , but this strikes me as kind of a hack rather than a natural use of the \{…} syntax. A distinctive single-character prefix would be better.)

—Guy


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-observers/attachments/20240315/12764663/attachment-0001.htm>


More information about the amber-spec-observers mailing list