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

Steven Schveighoffer schveiguy at gmail.com
Wed Sep 9 14:24:34 UTC 2020

On 9/8/20 9:32 PM, Avrina wrote:
> On Tuesday, 8 September 2020 at 13:32:10 UTC, Steven Schveighoffer wrote:
>> On 9/8/20 8:10 AM, Avrina wrote:
>>> What's the purpose of toFormatString with a default spec? Why would 
>>> you ever want to have a default??? That's just some hacky workaround 
>>> from the previous DIP to circumvent some arbitrary rule. Why wouldn't 
>>> you have some sort of type map instead that maps a format string to a 
>>> type? All of that information is available.
>> Because the default spec should not be constrained by the language 
>> (e.g. always "%s" as DIP1027 specified). See for instance mysql 
>> prepared statements, where the spec is "?". This way the callee can 
>> decide what to put for default specs.
> That doesn't answer the question. A type map to specifier would do the 
> same thing, just better; actually doing the work for the user.

Sorry, I didn't read the full question. So yes, a type map would work. 
But I think actually, if we give people access to the format tuple list 
(as I have brought up in the other subthread), a specific mechanism 
inside druntime is not necessary.

I still want to allow the implicit cast to const char* to allow one to 
use C functions without having to wrap them. And in that case, you need 
a mechanism to generate the format string anyway. And there's no reason 
not to expose it for other users (I'm thinking of mysql-native, which 
uses a single specifier for all parameters, '?'). We can handle the 
easiest case, and leave the more complex ones to the user.

> The way you have to pass the interpolated string for it to work makes it 
> almost completely useless. Requiring all format specifiers to be defined 
> by the user is counter intuitive compared to using an overload. There 
> are many C libraries, they require you to write bindings in D anyways, 
> it would not be that difficult to add an overload for interpolated strings.

The DIP does not prevent someone overloading printf to deal with it in 
your specified manner. BUT if you don't want to do it, there is no harm 
in allowing the call to proceed.

Now, printf could be overloaded, yes. We could make it work. It's not 
part of the DIP though. The point about writefln is salient because it 
will not work without an overload, and people will definitely expect 
writefln to work with interpolated strings.

>>> Implicitly converting to char* on a condition like 'hasAllSpec' is 
>>> just asking for trouble. This special case isn't required, it will 
>>> only introduce bugs;
>> All vague statements, do you know of any specific trouble or bugs?
> The DIP lists one? The CreateWindow example, if the specifier is given, 
> you can call a function with the wrong arguments that weren't intended. 
> The only way to avoid this is if you specifically create an overload to 
> avoid the implicit conversion. This should not be the default.

The key phrase in that is "if the specifier is given". Why would you add 
a specifier if you didn't understand what you are doing?

The point of that is for cases like i"my name is $name", which will NOT 
convert implicitly to a const char *. The thought process goes:

1. I've used interpolated strings in (Python | Javascript | ...).
2. Oooh! D has interpolated strings, let me just do that.
3. Compiler says "no, use .idup".

But if you are aware of the mechanisms of the interpolation spec, and 
you want to specify the formatting fields (e.g. if you are doing this in 
printf, you are already used to doing it), then it just works.

> If there is any implicit conversion happening for an I telrpolated 
> string, the only valid case would be one where it is converted to the 
> finalized string. Which isn't possible the way this is being implemented.

It is true this is not possible.

>>> The 'toFormatStringImpl' and friends implementations should just be 
>>> removed. Its simple enough that anyone can implement it, not.like 
>>> there is a performance benefit anyways as it is just going to be 
>>> using CTFE, like a library implementation. It is also too specific, 
>>> something like an sql query would just put a number depending on the 
>>> order of the parameters. So in that case it isnt really a specifier 
>>> for the argument some much as which argument should go where. I can 
>>> only imagine how confusing and error prone that is going to be, 
>>> especially since you have to specify every single argument if you 
>>> dont implement your own wrapper or overload to fix this.
>> These are implementation details, and not necessarily the final 
>> implementation. The real API is specified in the description.
> Yes, and the features they provide is what should be removed. There's no 
> point to being able to call a C function with an interpolated string 
> without an overload, see above.

Programmers are lazy. If I can do:

import core.stdc.stdio : printf;

printf(i"hello ${%d}name");

That might be enough. It might bug me that I have to always specify 
formatting specs, and then I'm motivated to write an overload. But it's 
not necessary for the purposes of this language change.

>> The numbered SQL problem is definitely one that is troubling -- you 
>> have to put in a placeholder for the number, and then replace it with 
>> the correct value, which means 2 passes of compile-time string 
>> generation. However, this is something that could be improved upon if 
>> the type provides access to the raw spec sequence, or allows a 
>> different way to build the format string (I have some ideas).
> The sequence is accessible publically, at least with the given 
> implementation as it is just a template. If that is not currently 
> intended then the DIP implementation should be fixed, and that makes the 
> situation with the 'toFormatString' default specifer much much worse. 
> The user is forced to use it and can't implement their own type map to 
> specifier to make interpolated strings function without having to have 
> the user forcibly put specifiers in their  interpolated strings for 
> types that don't match the default.

The DIP implementation is an example, and while usable, was not intended 
as a defining part of the spec. In fact, I have conceived of a different 
mechanism that would break anything that depended on having that 
specific implementation, but would still satisfy the DIP requirements.

I have since changed my view that the template parameters should be 
visible. They are visible anyway by introspection, and as you and others 
have pointed out, the way you would have to use the intended interface 
to process formatted items with the format string means 2 passes over 
the format string at compile-time.

In other words, the compiler would (in this implementation) separate out 
the data for us in a nice way, but the only way to access it is to 
generate a string, and then have to split apart that string again to 
process it a different way. There's no need for that.

>> Note that we are trying to prevent people from abusing the 
>> implementation to achieve "AST Macros" as Walter likes to put it. If 
>> we can provide a better way to generate the formatting, and still keep 
>> this property, it has a better chance of being accepted.
> It'd be better if this wasn't accepted then, rather than adding a 
> crippled feature that's counter intuitive for a user to use.

I agree. We will have to be convincing that allowing access to the 
format specifiers and string data separately does not equate to AST macros.


More information about the Digitalmars-d mailing list