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

Steven Schveighoffer schveiguy at gmail.com
Sun Feb 2 20:13:36 UTC 2020


On 2/2/20 2:36 PM, Adam D. Ruppe wrote:
> 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.

I'm sure I would rather use that than readf with format string and 
trailing parameters. And why would it "rarely" do 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.

Well, yeah. It's not limiting scanf, because scanf uses pointers. Either 
solution works there. But not for something like readf.

> 
>> 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.

I don't know for sure what possibilities are unlocked by this, but I 
know that the struct implementation has limitations that the naked tuple 
does not. Avoiding limitations means we could potentially find something 
genuinely useful that would have been blocked with something that has 
limitations.

I think we could get the best of both worlds if the interpolated string 
itself was not just a string, but rather a library-defined type (well 
something slightly more special -- it should implicitly cast to a 
null-terminated immutable(char)* if needed, just like string literals). 
You'd get overloading capabilities to do something custom with 
interpolated strings, and you would get all the niceties you would get 
from the struct solution, but without the limitations.

> 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.

I don't think this is the right route either. Putting "special" types 
into the language is something we're trying to move away from (it irks 
me still that the AA is not yet a library type, and needs TypeInfo to work).

> 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 readf example is a real world use case.

> 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");

This can be handled if the iterpolated string has a different type than 
a normal string, allowing overloading.

> 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>"

This can work with the DIP as-is.

EscapedString toEscapedString(EncodingStyle, T...)(string escapedFormat, 
T items)

> 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.

Both have benefits, and both have limitations. I feel the limitations of 
the struct are that it doesn't allow whole categories of usage. The 
limitations of the tuple are that you'll have to parse the generated 
string again after the compiler already has done it (and again, this can 
be solved with a new type for the string).

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

I think anything javascript does with interpolated strings, we can do. 
We just have to write the function to do it.

> 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.

I see no difference in saying "you can access printf, you just need to 
put in a little .c at the end" vs. "you can access assignment to string, 
you just have to put a little .format at the end".

The to-string potential is just fine with the DIP. That's mainly what 
it's for. On the to-string side, both ideas have merits and drawbacks, 
and I view them quite ambivalently. The from-string (as you call it) or 
compile-time potential is non-existent in the 
"interpolated-string-to-struct" idea, so it's a clear win for something 
that gives you a tuple of what you passed in.

I would vote a resounding yes to this DIP + making the interpolated 
string a new type, but still a solid yes on the DIP. I would not vote no 
on the struct idea, but I would not be as positive about it.

And we can actually add later the idea of making the interpolated string 
a new type after this DIP is implemented, mitigating a lot of the 
concern here. I don't want to let perfect be the enemy of good.

-Steve


More information about the Digitalmars-d mailing list