Discussion Thread: DIP 1036--Formatted String Tuple Literals--Community Review Round 1

Adam D. Ruppe destructionator at gmail.com
Fri Sep 11 19:59:35 UTC 2020


On Friday, 11 September 2020 at 19:31:33 UTC, Paul Backus wrote:
> The solution is to use the type system.

This is exactly what the DIP does!

Something serious must have gotten lost between my brain and the 
text.

> Not sure what you mean by this. The Phobos functions that use 
> the existing argument-list conventions already do error 
> checking; is there something they're currently missing?

This is kinda a rephrasing of the other three items (though, of 
course, introspection can do a lot more than just error checking, 
like I imagine a world where we gather translation strings like 
gnu gettext but 100% with a stock D compiler, no need for add-on 
tools) - by providing a new type, you can not only catch it at 
function overload / template constraint level, but you can also 
catch errors inside the format string itself.

You said:

> We can already do this with existing D features. See for 
> example `std.format.format`, which has an overload that 
> introspects the format string at compile time.

Indeed, and the DIP text has this example:

https://github.com/dlang/DIPs/blob/15537f9b36afa48f1c1cd57468e8c77f8f2499dd/DIPs/DIP1036.md#usage-in-existing-string-accepting-functions

<quote>

auto writefln(Fmt, Args...)(Fmt fmt, Args args) if 
(isInterpolationSpec!Fmt)
         return std.stdio.writefln!(fmt.toFormatString!"%s", 
Args)(args);
}

These ensure that interpolated strings just work for their most 
likely target functions while also providing a new benefit: the 
format string, including user additions via ${}, will be checked 
at compile time, even when passed as a run-time argument.

</quote>


Look very carefully at what it is doing there... it does a 
compile time check of a runtime argument through its type, 
actually ignoring the runtime pointer to it. Since a different 
type `Fmt` is generated for each unique i"" instance, you can do 
the same compile time optimizations format does *without* the 
explicit overload.

It is valid to pass that format string as a template argument 
since it is generated from the *static data*, encoded in the 
type, not from the runtime string. This is also the reason why 
"All format specifiers must be known at compile time" is listed 
under Limitations.

So let's say I call

string world = "lol";
func(i"hello ${%d}world");

func's implementation is free to inspect that format string at 
compile time! It might forward to the `writefln!fmt(args)` in 
which case it actually gets to leverage existing language 
features in a new way to check that %d/string mismatch and report 
it in a way that is impossible with normal writefln today (you 
must use the explicit template arg overload version at the call 
site).

This DIP builds on D's unique strengths, enhancing existing 
opportunities. None of the others come close, they're just syntax 
sugar.


More information about the Digitalmars-d mailing list