DIP 1027--String Interpolation--Final Review Discussion Thread
Arine
arine123445128843 at gmail.com
Mon Feb 3 05:10:13 UTC 2020
On Monday, 3 February 2020 at 03:57:09 UTC, Adam D. Ruppe wrote:
> 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.
Part of the whole reason is that this works with printf(), the
examples in the DIP almost exclusive use the C functions. Why
stop short of custom types?
> 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
> }
Implement string_is_ok() for me. How easy is it to implement to
verify it is valid for your own purpose while also working around
the printf formatting. Ensuring that it correctly interprets all
of printf's features.
> 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.
You can have that without the formatting, or having to add extra
meta data so you can link which argument goes with what index in
the format array. You get all of this if you don't use a
printf-style formatting string. It doesn't have to be added ontop
with a bandaid.
> 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.
The biggest problem here is that toString() then doesn't know or
understand the context it is being used in. You'd have to write
some sort of wrapper and then it starts to become convoluted. At
that point you are just trying to imitate a solution that doesn't
use printf formatting.
That then has to use a delegate, and if you have to do something
like insert one character at a time, it won't be ideal making so
many calls like that. Especially if you are concerned with
performance. Calling sink() multiple times could also cause
reallocations. It all depends on how format/writef or whatever it
is you are using is implemented. That generic function isn't
going to know about it as well as whatever you are implementing.
Such as if you want to implement a @nogc solution. There's no
phobos implementation for that. Your on your own to implement
your own @nogc solution and you're stuck having to implement this
monolithic format spec.
You can respond to arbitrary formatting, but what does the
compiler choose to insert? The DIP makes no mention of this.
These are all lacking details that shouldn't be plugged as they
appear.
> 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.
Where did you get that? The DIP doesn't mention that. So what is
the format string in this case? That's the first point of
failure, when it has to decide what format specifier it has to
put into the format string.
Only the first example is what I'd deem good enough to implement.
The other examples that use a printf-style format is showing the
inadequacies that are created from using it.
> 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...
You can't make your own @nogc function with custom types so
easily. This DIP seems to be hellbent on supporting C functions,
but at the end of the day it won't be able to support @nogc
without having to completely create your own solution that
implements printf-style formatting. That's not something anyone
is likely to do. Supporting @nogc would be a better goal than
supporting the C functions. Just calling toString() for the C
functions isn't sufficient.
That's why people would want to use it with C functions, is so
that it is @nogc. You're fine with not having custom types work
with C functions, but is that really fine? D doesn't have an easy
alternative and requiring the printf format spec be utilized
makes it incredibly more difficult to roll your own solution.
It's ironic, this DIP is pushing for printf C functions to be
usable so it can work with @nogc. But it makes it more difficult
to support @nogc and your own custom implementations because
phobos inadequately supports @nogc. Even if it did have some
@nogc format, you'd still be impeded from optimizing your own
implementation and would rely on whatever kind of optimizations
are done in @nogc format. Which might not fit your use case.
More information about the Digitalmars-d
mailing list