DIP 1027--String Interpolation--Final Review Discussion Thread

Adam D. Ruppe destructionator at gmail.com
Sun Feb 2 19:36:48 UTC 2020


On Sunday, 2 February 2020 at 18:46:36 UTC, Steven Schveighoffer 
wrote:
> The problem I have with the struct mechanism is that it 
> enforces the parameters are all non-reffable data.

This is why I at first wanted a pure language solution instead of 
the hybrid solution now (language provides syntax sugar, library 
provides implementation), but I'm not actually sure this is worth 
fighting over.

> int apples;
> int bananas;
> readf(i"I have $apples apples and $bananas bananas");

It is kinda cool that this can work, but really, do you think it 
is legitimately useful? readf is so weird in how it works that 
you'd very rarely find a case where the interpolated string even 
does the right thing.

Moreover, this would also require ref; it wouldn't work with 
scanf. So that limits it either more.

But consider if you did want to do something like this, you could 
i"$(&apples)"... which actually would work with scanf as well as 
with the struct; a pointer can go in there easily enough.

> struct S {}
> foo!(i"I'm passing $S as an alias/type, with some formatting 
> data around it");

Again, I think that is cool but not useful enough to justify 
compromising other cases. I'll take it if and only if it comes 
for free, and the naked tuple does not come for free.

A pure language struct btw can do this - the compiler, instead of 
calling a library function, just creates the type internally. 
Then it can declare them as aliases as needed. But that opens up 
other complications.... and really, what's the value? Why would 
you want an alias in the middle of a string? There might be 
some... but I can't think of one right now and I suspect there'd 
be a better way anyway.

But let's just be careful not to damage real world use cases in 
the name of "that might be cool in theory someday". The struct 
has definite real world use cases... the alias/ref tuples not so 
sure.


> The biggest thing that the DIP has going for it is that there 
> are lots of functions which have a format string + args

Yeah, I do like being able to specify a format thingy 
(`${%3d}bananas`) in there. That's something I'd definitely see 
being legitimately used.

Though I'd probably prefer the format string to be built in a 
library, I like that bit enough that I want the magic lowering to 
do something with it somehow.

But otherwise it is easy for a library solution to provide format 
strings as needed, transparently to the user. And a library 
solution can handle the DIP's limitation:

string tool = "hammer";
writefln(i"hammering %s with $tool", "nails");


How? Well, since it is an independent object, it knows what 
arguments it had! It could translate itself before going to 
outside uses. And especially with a method to produce a format 
string, it can even be smart enough to escape % to %% in the 
interpolated things.

So that becomes

writefln(_interp!("hammering %s with ", "")(tool), "nails");

and then _interp returns its helper struct. Well, if we do 
implicit toString and tool == "%s" well, lol we just poisoned our 
format string.

But at the same time, we could provide a method to escape the 
interpolated thing - and writefln could overload based on this to 
just call that. writeln knows what it needs.

So it'd be like

void writefln(__Interp fmt, ...) {
     string f = fmt.toEscapedString!(a => a.replace("%", "%%"));
     // forward back to the normal one
     writefln(f, ...);
}


Then that toEscapedString method on the struct calls the given 
delegate on each user string as it is appended to the final 
result. Allowing us to properly encode it in a particular context.

You could us the same thing with html:

string user = "<try_injection>";

string myHtml = i"<b>$user</b>".toEscapedString!htmlEntitesEncode;
// myHtml == "<b><try_injection></b>"


and ditto for any format you can imagine. The struct is flexible 
in so many ways that a tuple isn't! And it is easy to use.

Javascript's string interpolation even lets us do this. Do we 
want D to be defeated by JAVASCRIPT?!!?!?!?! lol


(this kind of thing btw is another argument against an implicit 
toString on alias this. Like I propose that to be friendly to 
people who insist `string s = i"$foo";` must work, and it is cool 
that we can, though I personally think it should be a decision. I 
don't care about GC, but I do care about proper encoding of 
output.)


Again, back to your main counter point, do we want to sacrifice 
all this *definite* value for possible uses in theory for ref 
arguments? I'm not against refness per se (I do find it a lil 
weird, but still)... just I don't think it is worth sacrificing 
anything for since the to-string potential is far more clear than 
the from-string readf potential.


More information about the Digitalmars-d mailing list