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

Adam D. Ruppe destructionator at gmail.com
Wed Feb 5 16:04:07 UTC 2020


On Wednesday, 5 February 2020 at 15:20:56 UTC, Steven 
Schveighoffer wrote:
> 0. You have missed one edit:

thx, I'll come back to it later.

> 1. I hate that this doesn't work:
>
> alias toFormatString!null this

Yeah, I assumed it would because an eponymous template to an enum 
string does work. But then you lose the ability to detect the new 
type (maybe if we had typedef LOL).

But it doesn't... and you know that createWindow one actually 
really gets to me. I think that is likely to be a big problem 
with unintentional interactions confusing people. And, of course, 
other people's concerns about implicit GC contextual allocations 
are fair too.

However, I agree it is likely a bug. That said... this is one of 
those trade-offs that could go either way anyway.

Of course, it is purely in the library which in theory can be 
tweaked more easily in the future.


> 2. I disagree that you shouldn't be able to do 
> writefln(i"someint : $someint")
>
> But your CreateWindow example is also pretty compelling.

Yeah, this is back to the both-sides-have-merit trade-off. I 
could probably go either way - we could default to permissive and 
handle more cleanly with another lib overload too (which we also 
talked about earlier in this thread). Or restrictive with helper 
functions as I'll get into next.

> It would be nice to make "send the first parameter as a string" 
> opt-in. Is there a way we can do that without requiring 
> overloads?

I can't think of a perfect way. Can't use a helper template on 
params (call(help!i"xx")) since that triggers "variable X is not 
available at compile time", and can't do a helper UFCS function 
(call(i"xx").help) since they cannot return a tuple.

We could do `help!call(i"..")` though... opt-in at the call site 
on the function, not the args. (I'm using "help" cuz i can't 
think of a name right now but meh). So basically a template that 
makes a new overload right there.

callWithFirstAsString!writefln(i"...");

and the implementation is

auto help(alias fn, T...)(T t) {
     return fn(t[0].toFormatString!"%s", t[1 .. $]);
}

so that's easy enough. And of course you could provide other 
customization arguments in there like a different default 
formatter etc. So that could be our hook into existing functions.


And of course that could be done for printf too instead of alias 
const char* this, but then we're talking an import so... again 
not perfect but plenty of good enough library options we can talk 
about or even develop independently once we get the core language 
rewrite in place.

Interestingly a printf one could inspeect the types of t[1..$] to 
change the default specifier, e.g. if(is(typeof(t) == int) fmt ~= 
"%d" else static assert(0) and so on. So it could actually work 
quite nicely. Of course do that as a ctfe to enum so it isn't GC 
at runtime. (or failing that use a stack buffer.)

It just needs that help!printf instead of printf. Which we can 
debate. (I actually would prefer to go that way but I'm trying to 
maintain Walter's printf desire too.)

But lots of options. With zero changes to dmd itself once we get 
this change.

> 3. I'm also not sold on the "if they provided a format 
> specifier, they know it returns a tuple" logic. Plenty of 
> existing string interpolation libraries provide ways to format 
> the parameters into strings, and still can be used as strings.

Yeah, I just figure if the user is specifying all the strings it 
means they must have at least thought about the format of those 
specifiers. They might be doing it for other purposes or just be 
wrong, but eh.

Note the only change that did is enable `alias this` conversions; 
you can still ignore it and use the other facilities.


> Note that C# does something pretty cool [1] (as I just looked 
> it up to see what other interpolation libraries do)

Indeed, not bad. It looks like C# is similar to my old proposal, 
creating an object :) Then we could implicitly convert to a 
single string with `alias toString this` or use the specialized 
type. but of course i think this tuple is a wee bit better since 
it lets us keep `ref` and `alias`. Might also be relevant with 
other storage classes like `scope`, `return`, etc. So that's the 
trade off there (with current D at least).

I could go either way, but like I said in my other message with 
the list, I think the tuple's potential is indeed worth 
sacrificing the object's convenience (but idup and other 
functions 95% make up for that anyway!).

> Inspired by that C# type, maybe "formattable tuple" is a good 
> description.

that would work.


More information about the Digitalmars-d mailing list