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

Adam D. Ruppe destructionator at gmail.com
Mon Feb 3 03:57:09 UTC 2020


On Monday, 3 February 2020 at 02:57:41 UTC, Arine wrote:
> I don't think you should compromise. Using printf as the basis 
> just limits what can be done with an interpolated string. How 
> do you handle custom types?

Eh, that's a solved problem. See: 
https://wiki.dlang.org/Defining_custom_print_format_specifiers

The format string is incredibly flexible and the tuple proposal 
does a fairly good job maintaining all available information 
until the last minute.

With the % -> %% encoding, it is also possible to reliably* 
determine which

* with the exception of a user-defined format string that breaks 
this convention. e.g. `i"${not_percent}(foo)"` will not be able 
to tell for certain that foo is tied to not_percent, and this can 
throw off processing of all subsequent arguments as well. Maybe 
we should do something about this.

> Since printf() wouldn't be able to take a custom type.

Yeah, printf would likely fail with custom types, but that's 
printf's limitation - D's writef works well with them, including 
various custom format specifiers and allocation-free output.

And other custom functions, provided we identify the format 
string as such, can do any special parsing of it.

With my proposed addendum, even compile-time validation of the 
format string is possible in consumer functions:

void my_thing(Format, Args...)(Format fmt, Args args) {
     static if(is(Format == _d_interpolated_string!S, string S))
       static assert(string_is_ok(S));
     else
       static assert(0, "you didn't pass an interpolated string");

    // use args according to fmt
}

(I would actually recommend we make the name and interface a wee 
bit more friendly in the library for user consumption, including 
methods that can be tested without tying us to just one argument 
like that is expression does above, for future expansion 
potential... like I kinda want to also say how many arguments 
there are as CT params there, or even the slices of that string 
that represent format strings - that would IMO be the holy grail 
as we can not only get how many args but exactly where they are 
without reparsing the string - but I digress. Regardless, the 
compiler can output the _d_whatever ugly thing and I like to use 
ugly things in these examples in an effort to avoid people 
arguing over the name when I'd rather focus on the underlying 
concept.)

But anyway since the format string is actually part of the 
*type*, we can overload on it and extract the original string as 
a compile-time constant - including when passed as a runtime 
argument list - for further processing.

> For each object toString() would allocate it's own buffer, when 
> it could be constructed in place.

void toString(
      scope void delegate(const(char)[]) sink,
      FormatSpec!char fmt)

is already possible with D's existing format function on custom 
objects. No allocation and you can respond to arbitrary 
formatting details as specified there.

So your example:

> Or to retain the type, it would then not work with printf().

A custom type wouldn't work with printf with the DIP as it 
stands. It does not attempt to convert anything, it just forwards 
the arguments.

Similarly your function could require that the format strings 
must just be %s and you don't support customization. The 
implementation there can be as simple as scanning forward for % 
and a compile-time template could break it up into an array for 
you with no runtime trouble. Or you could only support a custom 
format that the user needs to put in the ${here}(var) thingy.

I'm *very* close to supporting this DIP, it isn't actually that 
bad. As it is, I'd have to recommend we defeat it, but if we can 
all agree to amend it to put in the template thing we can fix 
everything. Even with just the one string arg, we can do a lot 
with it...

(my struct would make simple cases simpler - you can just 
.toString it without imports or even alias toString this - but 
the template does actually allow more custom flexibility.)


More information about the Digitalmars-d mailing list