Feedback Thread: DIP 1036--String Interpolation Tuple Literals--Community Review Round 2

Steven Schveighoffer schveiguy at gmail.com
Fri Jan 29 16:55:05 UTC 2021


On 1/28/21 6:06 PM, Paul Backus wrote:
> On Wednesday, 27 January 2021 at 10:33:53 UTC, Mike Parker wrote:
>> This is the feedback thread for the second round of Community Review 
>> of DIP 1036, "String Interpolation Tuple Literals".
> 
> DIP 1036 takes two different approaches to string interpolation and 
> attempts to merge them together into a single proposal. In broad terms, 
> those approaches can be characterized as follows:
> 
> 1. The convenient approach: the language and runtime take care of string 
> conversion and memory allocation for you, and you don't have to worry 
> about any of the details.
> 
> 2. The flexible approach: the language splits the string apart into 
> interpolated and non-interpolated pieces, and it's up to you to decide 
> what to do with them.
> 
> DIP 1036's proposal for #2 is very good, and its proposal for #1, while 
> missing some important details, appears to be fundamentally on the right 
> track. Either one of these proposals would make a fine DIP on its own. 
> The problem with DIP 1036 is in the way it attempts to combine the two.
> 
> Fundamentally, the goal that DIP 1036 is aiming for is to give the 
> programmers who want convenience the convenient version, and to give 
> programmers who want flexibility the flexible version. While this is an 
> admirable goal, fully achieving it requires reading the programmer's 
> mind, which is infeasible given D's current level of compiler 
> technology. So what DIP 1036 does is attempt to *guess* what the 
> programmer wants, using a rather crude heuristic: if the code compiles 
> with the flexible version, the compiler is to assume that's what the 
> programmer wants; otherwise, it assumes they want the convenient version.
> 
> As with any heuristic or approximation, there are edge cases where this 
> breaks down. One of them is called out in the DIP itself--type inference 
> via `auto`--but it is not hard to imagine others. For example, a 
> programmer who writes
> 
>      tuple(i"Good morning ${name}", i"Good evening ${name}")
> 
> ...is probably not going to get what they intended, even though their 
> code compiles.

This is quite the unique edge case though. Any proposal that provides 
the flexible version is going to have trouble with tuple as it is now. 
DIP1027, Jonathan Marler's PR, etc would all do something "unintended" 
(though one could argue it may be intended, depending on the usage).

There are solutions that can be had. For instance, tuple could be 
instrumented never to accept parameters that contain interpolation 
literals. Therefore, the idup rewrite happens, and they get what they 
expect. This is not hard to solve.

But sure, one can definitely find edge cases for any proposal, 
especially in D where one can just write:

auto foo(T...)(T args) {
    ...
}

> 
> Every D programmer who wants to make effective use of DIP 1036's 
> interpolation literals will have to go through the process of learning 
> when .idup is required, when it's optional, when it's 
> allowed-but-unnecessary, and when it's forbidden--which means that, in 
> practice, they will have to learn how it actually works, under the hood. 

This is not my interpretation at all. I can't think of a reasonable case 
aside from your tuple example where idup is required (if that's what you 
want). Can you? And the tuple issue can be solved quite easily.

> This is not a desirable trait for a language feature that's intended to 
> make programming *easier*.

Your logic is not very sound. It's ironic to say the language doing what 
you expect for 99% of cases is a higher burden than requiring you to 
write it yourself for 100% of cases.

> 
> Ultimately, I think attempting to guess the programmer's intent is the 
> wrong way to go here. Either force them to spell it out explicitly (with 
> a call to .idup, .text, etc.), or take away the choice and give up on 
> one of the two approaches.

I want to say something about this idea of doing only one or the other.

Let's say you want to create a language feature for string interpolation 
that always results in a string. Because you need to process the values 
and convert them to string data at runtime, you need a library function 
that accepts the data.

How do you write such a library function? If this was D1, the way would 
be to use variadic parameters, passing the TypeInfo of each item, and a 
void *, and then you'd have to provide a universal way to convert all 
types to strings.

But this is D2. So the correct way to do this is to pass a template 
variadic argument list to a runtime function, and have the runtime 
function do the conversion.

If you are doing that, you are ALREADY having the compiler generate the 
expanded form. It's just always preventing anyone from using it 
directly. I can't imagine a DIP with this kind of "implementation 
detail" hiding the actual treasure of the feature being acceptable to 
the community.

If you want to implement just the tuple version, now you run into the 
unpleasant result of having the simplest expected thing fail. That is, 
when you assign what looks like a string to a string, it fails. When 
passing what looks like a string into a string parameter, it fails.

Both of these options are feasible, and can be argued for, but are not 
what I would expect for a D language feature. The first option is hiding 
everything useful from the user instead of using the power of D 
metaprogramming. The second option is right up D's alley, but places a 
heavy burden on those who want to just use strings. The combination of 
both is a cohesive whole which leaves very small edge cases to be dealt 
with by function authors (and provides a straightforward clear way to do 
so).

If this DIP gets accepted that does not mean the work is done. It means 
the opportunity is opened for people to take advantage of it. Yes, there 
are edge cases, but the solutions are apparent and readily available, 
and the default behavior without such changes is still reasonable. And 
this does not take away from the fact that the vast vast majority of 
non-edge-case *just work*.

-Steve


More information about the Digitalmars-d mailing list