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