On 13 Mar 2024, at 13:13, Guy Steele wrote:

> … Well, just off the top of my head as a thought experiment, if I had a 
> series of SQL commands to process, some with arguments and some not, I would 
> rather write
>
> 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($”INSERT INTO foo (name, title) VALUES (\{other name}, \{other 
> job});”);
>
> than
>
> SQL.process(ST.of(”CREATE TABLE foo;”));
> SQL.process(ST.of(”ALTER TABLE foo ADD name varchar(40);”));
> SQL.process(ST.of(”ALTER TABLE foo ADD title varchar(30);”));
> SQL.process(ST.of(”INSERT INTO foo (name, title) VALUES (‘Guy’, ‘Hacker’);”));
> SQL.process(”INSERT INTO foo (name, title) VALUES (\{other name}, \{other 
> job});”);

OK, yes.  I think a simpler example is needed to answer my question more fully. 
 In this example, the name “foo” is given as a literal.  But, even if only as a 
workaround, it would probably not hurt code like that to quote such a name as 
an argument.  So:

> var foo = “foo”;  // or static final String FOO = “foo”;
> 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(”INSERT INTO \{foo} (name, title) VALUES (\{other name}, \{other 
> job});”);

And it’s not just a workaround here, it’s arguably better style (D.R.Y.) to 
factor out the name foo that links everything together.  Non-support of no-arg 
STs would possibly push users towards a more D.R.Y. style, possibly a good 
thing.

I think such multi-command examples, in many little languages, will tend to 
have some term like foo shared across phrases.  The very small example I’m 
looking for would ideally be non-factorable, just a little string with not much 
substructure.  Because if it’s factorable, then maybe the user should just 
factor it, and then it’s a ST with arguments.  And if it’s not factorable, then 
maybe it is some stand-alone thing that won’t be harmed by making it a canned 
constant, or making it via a factory method, or making it a true string which 
is introduced into the processor by other means.

Not all languages offend against D.R.Y. as much as SQL.  A more contextual 
stateful little language, like Forth or Turtle graphics or Postscript, might 
have lots of little fixed commands (like “left” for a turtle).  When we work 
with such little languages we sometime have lots of static final strings to 
help us find the commands and spell them correctly.  (Like static final String 
LEFT = “left” in class TurtleGraphics.)  That would maybe morph into lots of 
static final STs?

————————

OVERLOADS

Another possible answer, in the use case with SQL above, is that if the 
language processor expects lots of ad hoc non-factorable (or non-factored) 
strings, it should cater to that expectation by taking String as an overload 
option.  That places pressure on the API designer to perform the conversion 
(ST.of) on the fly.  And overloads can expand non-linearly when there are 
several arguments in play.  And there are sometimes ambiguity risks in some 
corner cases, as Maurizio has shown.  Still sometimes it’s a good tradeoff to 
add an overload, if the problems are in truly minor corner cases.  Or maybe 
allowing strings instead of STs gives up some optimizations?  But often it’s 
better to let the chips fall with API design and do the work to optimize 
whichever API turns out to be most user-friendly.  I don’t see (maybe I missed 
it) a decisive objection to overloading across ST and String, at least for some 
processing APIs.

————————

ALGEBRA

These examples also lead me to a different source of questions, which is 
whether or how the existing practice of string constant expressions (like 
static final FOO above) can or should connect to STs as well.  It’s an 
interesting line of thought, so I’ll write something here, but (bottom line) I 
don’t think we want to act on it, at least at first.

String constants have a privileged role in the JLS, and also in programmer 
practice (as with FOO above).  Can/should STs leverage this somehow?  Should a 
“constant ST expression” be an alternative to a ST literal?  I’m thinking of a 
String or ST constant like MY_FORTH_PROLOGUE which I stick at the front of some 
ST that I’m building.

But that would seem to require some way to concatenate such a string to an ST, 
an expression like ST ‘+’ String -> ST, which seems disturbing to me, but might 
actually make sense.  Or would nesting be better, something like `(define tp 
(foo ,@sub-tp bar))?  A variation of \{x} like \@{subtp}?  (And would there be 
javac constant folding rules for it, as well as dynamic rules for evaluation?)  
This is speculative brainstorming; I’m not seriously recommending it for now.

Still, continuing… If MY_FORTH_PROLOGUE should be a static final ST, then I 
want options for prepending it locally to ad hoc strings.  So the question 
about “what about constants” turns into a larger question, “what about ST 
algebra on ST expressions?”  If you allow constants to be defined non-locally, 
you need a way to combine them with “more stuff” locally.  This relates to the 
issue raised earlier of whether nested STs should be part of the ST API:  
Whether you concatenate two STs or nest one inside another, it seems you are 
doing some kind of generic ST algebra, generic across all uses of ST, not just 
for some processors.

And, circling back, if there were a way to fold ST literals together (with some 
non-local parts) then that would lead to another alternative to a “sigil” to 
disambiguate a plain string from a no-arg ST.  You’d use the concatenation 
operation (whatever that is) to combine an empty ST into the string that needs 
markup.  Kind of like when we say “”+x to abbreviate String.valueOf(x).

Given nesting or concatenation syntax, no-arg ST literals could be 
disambiguated by a prefix like ST.EMPTY+”…” or like “\@{}…”, which either 
prepends or nests a degenerate ST.  That could serve a role like $”…” in your 
examples, Guy, although of course a single-char sigil looks nicer.

Maybe we want some more algebra like that someday, but I am not enthusiastic 
enough to recommend it now.  I guess the most I’d recommend is somehow leave 
room for building up nested or concatenated literals, as a future addition.  
Allowing STs to start like “\{}…” would solve today’s disambiguation problem 
with a kludge like $”…”, and also a hint of more “algebra” in the future.

> 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(”\{}INSERT INTO foo (name, title) VALUES (\{other name}, \{other 
> job});”);

HTH

Reply via email to