February 04, 2020
On Tuesday, 4 February 2020 at 22:38:59 UTC, Timon Gehr wrote:
> Personally, I think it is ridiculous that the DIP focuses on printf over all other use cases so much yet in the common case, the proposed string interpolation will lead to access violations when used with printf in the most natural way, and it does not even support type safe formatting. This is not what people mean when they vote for string interpolation on a survey.

+1


February 04, 2020
On Tuesday, 4 February 2020 at 21:49:18 UTC, Steven Schveighoffer wrote:
> [snip]
>
> The intention is for __d_interpolatedString (or whatever) to return a struct that has an enum member which is the interpolated format string, which is then alias this'd to the struct.
>
> So the type should decay exactly into what the current DIP says. It should be 100% compatible with printf.
>
> But if you want to do something different with interpolated strings, you can overload your function to handle it specially. Once you do that, you have access to the original parsed interpolation string parts and formats.
>
> In short -- anything that would work with the DIP as currently written would work with this new proposal.
>
> -Steve

Thanks. I think my confusion was more related to Walter's DIP than your suggestion.
February 05, 2020
On Tuesday, 4 February 2020 at 22:38:59 UTC, Timon Gehr wrote:
> [snip]
>
> @jmh530: Have you read all the arguments made? Do you really think they are not compelling enough to at least warrant being addressed?

I've read each version of the DIP and all the arguments. Admittedly, if I don't understand why something's important, I skim (and I did a bit of skimming on this topic as it's not super important to me).

I think my confusion was more basic and related to the DIP itself, rather than the addendum. For instance, if I have a function
void foo(string x) {}
then I would have expected to be able to pass an interpolated string literal to it just as in any other. However, a closer reading of this DIP suggests that is not intended.
February 05, 2020
On Wednesday, 5 February 2020 at 00:01:53 UTC, jmh530 wrote:
> For instance, if I have a function
> void foo(string x) {}
> then I would have expected to be able to pass an interpolated string literal to it just as in any other. However, a closer reading of this DIP suggests that is not intended.

Right, that will not work with any of the active proposals.

Though with mine, you will get a type mismatch error if you try and you can put `.idup` on it to make a copy into a GC string. So it is still easy enough... while being possible to do *so* much more with it too.

(and even with Walter's original one, you can import std.format; and then i"xxxx".format() to do it too.)
February 05, 2020
On Tuesday, 4 February 2020 at 23:03:45 UTC, Adam D. Ruppe wrote:
> On Tuesday, 4 February 2020 at 18:41:20 UTC, jmh530 wrote:
>> [...]
>
> That would depend on the druntime implementation. I think my preference would be it implicitly casts to string and const char* if and only if all format specifiers are given by the user.
>
> [...]

Thanks for doing this work Adam. Especially knowing that it will likely be dismissed by the leadership, with a sentence or two of explanation :)  In my opinion, your DIP is the right way to do interpolated strings in D.
February 05, 2020
On Tuesday, 4 February 2020 at 23:03:45 UTC, Adam D. Ruppe wrote:
> I just wrote up a revised DIP based on Walter's to detail my current thoughts:
>
> https://gist.github.com/adamdruppe/a58f097d974b364ae1cbc8c050dd9a3f

So I didn't explicitly say this in the document, but you can prove it by running my sample code

void main() @nogc {
        string name = "interpolation";

        // I wrote out long form what
        // i"Hello, ${%s}(name.ptr)\n"
        // would be lowered to by hand.....
        printf(_d_interpolated_string!("Hello, ", _d_interpolated_format_spec("%s"), "\n")(), mixin("name.ptr"));
}


Observe how that *works* with @nogc.

Despite my specifically putting the format string builder inside a private method with an if(__ctfe) guard, called from a wrapper template to force a CTFE enum generating, it did not compile with -betterC, but this is a known bug in betterC, not a flaw with my proposal nor my sample implementation. See: https://issues.dlang.org/show_bug.cgi?id=19268

Of course, if we really wanted to, we could provide a separate implementation that works around the -betterC bug anyway, but even if we couldn't work around t, it would be ridiculous to cripple a new feature just because of a known bug in a niche dmd switch.
February 05, 2020
On Wednesday, 5 February 2020 at 02:44:53 UTC, Jonathan Marler wrote:
> In my opinion, your DIP is the right way to do interpolated strings in D.

so I put the author in there as "D community team effort" because it was your implementation of the tuple thing that changed my mind on interpolation being of any value to D at all, and IIRC you based that implementation on someone else's initial write up. And then of course in this thread, Steven changed my mind away from another idea and toward the core of what was here, and others too for a bunch of input.

And yes, even Walter's DIP introducing the format string thing is actually a really solid idea too - the printf compatibility is legit cool just because we *can*, and this will also aid compatibility with things like gnu getline among others, and the format string wrapper enables `ref` parameters, which I'm still a little iffy on... but that's something none of my previous encapsulation ideas would have been able to do. This is really a very small tweak from what he had.

So it is not *my* proposal. It is *our* proposal. We should all share in the credit...

...and all unite on insisting that leadership take our voices seriously.
February 04, 2020
On 2/4/2020 1:59 PM, Steven Schveighoffer wrote:
> On 2/4/20 2:12 AM, Walter Bright wrote:
>> On 2/3/2020 5:06 PM, Jonathan Marler wrote:
>>> Some applications want the "Strings and Expressions" form rather than the "Format String" form.
>>
>> To have "strings and expressions" then write it that way:
>>
>>      foo("I want ", i, " bananas");
> 
> To have "formatted string output", just write it that way:
> 
> writefln("I have %s apples and %d bananas", apples, bananas);

The reason for formatted strings is for formatting that is other than the default, and to interface with common functions that use formatted strings.

Strings and expressions are stuck with the default format. If you're happy with the default formatting,

    writefln("I want $i bananas");

is not much of any improvement over:

    writeln("I want ",i," bananas");

February 05, 2020
On Wednesday, 5 February 2020 at 05:26:30 UTC, Walter Bright wrote:
> The reason for formatted strings is for formatting that is other than the default, and to interface with common functions that use formatted strings.
>
> Strings and expressions are stuck with the default format. If you're happy with the default formatting,
>
>     writefln("I want $i bananas");
>
> is not much of any improvement over:
>
>     writeln("I want ",i," bananas");

I think it's still a significant improvement. In my experience, anything that forces you to context switch from "inside string" to "outside string" is a frustrating source of typos and 'mental hiccups'. The point of format strings is that you can "stay inside" the string context and open a *new* expression context instead of mentally pre-flattening the string tree out into a list of fragments. (This is also a significant weakness of mixin strings.)

In other words, the difference between ("I want $i bananas") and ("I want ", i, " bananas") is that one is (I want (i) bananas) and the other is ((I want ), (i), ( bananas)) - going down to nest vs going *up* to nest.

This may sound trivial, but trivial syntax enhancements matter, especially for a "top-ten" feature like format strings.
February 04, 2020
On 2/4/2020 2:38 PM, Timon Gehr wrote:
> Personally, I think it is ridiculous that the DIP focuses on printf over all other use cases so much yet in the common case, the proposed string interpolation will lead to access violations when used with printf in the most natural way, and it does not even support type safe formatting.

You seem to be arguing for both baked-in knowledge of printf format specifications, and against making it printf specific?

Replying not just to Timon here:

To clarify:

1. the DIP is not specific to printf, writef, or SQL formats. It has no knowledge of any of them. It isn't even specific to calling a function. It simply produces a tuple expression, the first of which is a format string constructed from user-specified (not builtin) formats.

The only exception is using %s if the user neglects to give a specification.


2. printf-aware checking can be added, but that would (and should) be an entirely orthogonal proposal, and would be effective with or without interpolated strings, as it has literally nothing to do with this DIP. A possible printf-format-checker would be run *after* the lowering to the tuple expression, and so would be equally effective for using or not using interpolated strings.


3. having the interpolator escape % by writing %% means that % becomes "baked in" as a special character. This is a completely unnecessary complication.


4. I repeat that I only use printf as an example because it is so well known and I don't have to spend a lot of time explaining what printf is and how it works. Note that writefln is also included as an example. There is nothing at all printf or writef specific in the design.


5. This proposal is not at all intended to be a substitute for knowing how printf formatting works. You're still going to have to remember to use %d for printing integers rather than %s or %g. This alone suggests that the DIP is not focused on printf.

----

The DIP is minimalist. This is intentional, as it proposes a very simple and straightforward rewrite of a literal into a tuple expression. Understanding tuple expressions (an existing D feature) is essential to understanding the DIP. This is a technique called "lowering" and is a great way of simplifying the semantics of a language and reducing corner cases and implementation bugs. Other examples:

1. the compiler rewrites 'while' loops into 'for' loops

2. the compiler rewrites RAII constructions into `try-finally` constructions

In fact, the compiler could profit from doing a lot more lowering transformations.