September 12, 2020
On 9/11/20 10:48 PM, Adam D. Ruppe wrote:
> Also Steven is seeing if he can make auto-conversion work and I'm mulling over your idea of two different prefixes. t"..." yields the tuple, i"..." automatically calls idup (or whatever).

I am legitimately scared at this point.
September 12, 2020
On Saturday, 12 September 2020 at 09:06:00 UTC, SHOO wrote:
> And idup uses std.format.

We're thinking about dropping the format string part, which would immensely simplify this implementation to the point where there's no need for the import anymore.

It also simplifies the syntax and the explanations. The cost is a bit less compatibility with existing functions, and if you do need to specify formatting, it would be done by functions instead of by strings.

So like i"${%x}number" would have to  be i"$(number.hex)" or something instead.

There's some details to work out but it looks like a good direction right now.
September 12, 2020
On 9/12/20 5:27 AM, claptrap wrote:
> On Saturday, 12 September 2020 at 02:48:38 UTC, Adam D. Ruppe wrote:
>> On Friday, 11 September 2020 at 20:46:05 UTC, Paul Backus wrote:
>>> This solves the issue of accidentally passing the wrong thing
>>
>> And processing an i"" is trivial; it is just either a string or a subclass of string (aka a struct with alias toString this) and you'd just use it like that.
>>
>> The t"" is more composable; it is the superior language feature. But I can live with a convenience compromise.
>>
>> So we'll see.
> 
> Thats a step in the right direction IMO.

To me it seems akin to that moment you realize the practical joke has gone too far.

Flight attendant: "More of anything?"
Seinfeld: "More of everything!"

So now we're talking about not one, but two interpolated strings. Deus Ex Machina and all that. (For fun and giggles: Good Work six months from now will make their semantics juuuuust slightly different.) How is this great design? There is so much to be said about sense and sensibility; living under one's means; economy of mechanism; creating a part of a whole; and such.

I really feel we miss a different mind on the team. Someone who just thinks differently. Like an architect. Or a novelist.

One possibility - which sadly comes from my limited engineering mind - is to create and observe budgets for metrics that are proxies to complexity.

* 1000 words in the DIP
* 1000 words complete documentation
* 1000 words tutorial
* 1000 lines in total implementation (compiler + library)
* 30 seconds explanation that doesn't omit any dangerous subtleties

September 12, 2020
On Saturday, 12 September 2020 at 12:40:21 UTC, Andrei Alexandrescu wrote:
> I am legitimately scared at this point.

Posts like this add nothing of value to the conversation. You should at least say why.

But you have to understand there is literally no winning. Provide a convenience feature and people complain it is not composable. Provide a composable feature and people complain it is not convenient. Provide both and get this.

At a certain point, we'll have to tell one group (or more) "sorry, you lose". Personally, I say we should make it composable and tell everyone else to suck it up and call a function on the result. But I'm trying to be a team player here and at least explore the options before dismissing them.

September 12, 2020
On Saturday, 12 September 2020 at 12:37:14 UTC, Andrei Alexandrescu wrote:
> On 9/11/20 5:36 PM, Stefan Koch wrote:
>> 
>> could be a compiler tuple which doesn't need std nor object.d.
>
> Shouldn't because it needs to be expandable on demand, not implicitly.

The only way I can think of to do this that works in the general case is something like the following:

// Before
writeln(i"Hello $name!".expand);

// After
template Pack(Args...)
{
    alias expand = Args;
}

auto ref __interpexpr1() { return name; }

writeln(Pack!("Hello ", __interpexpr1, "!").expand);

The reason you can't use a struct (that is, a "run=time tuple") is that the mapping from *expressions* to *values* is not injective--it discards information about ref-ness and lazy-ness (and maybe others I haven't thought of?). And the reason you have to "quote" each expression by wrapping it in a function is that template argument lists only accept symbols, not expressions.

I'm not sure if I like this better or worse than DIP 1027's "naked argument list" approach.
September 12, 2020
On Saturday, 12 September 2020 at 02:48:38 UTC, Adam D. Ruppe wrote:
> On Friday, 11 September 2020 at 20:46:05 UTC, Paul Backus wrote:
>> This solves the issue of accidentally passing the wrong thing with i"Window $id", and also prevents non-interpolation-related accidental usage, like mixing up the width and height.
>
> yeah that's legit.
>
>
> So what we're considering is simplifying it a bit and dropping the embeddable format strings. Also Steven is seeing if he can make auto-conversion work and I'm mulling over your idea of two different prefixes. t"..." yields the tuple, i"..." automatically calls idup (or whatever). t is the building block, i is the "just give me a string" shortcut built on top of t.
>
> So in my next draft, processing a t"" yourself looks like:
>
> auto foo(InterpList, Args...)(InterpList interp, Args args) {
>     string ret;
>     foreach(idx, arg; args) {
>         ret ~= interp.strings[idx];
>         ret ~= to!string(arg);
>     }
>     ret ~= interp.strings[args.length];
>     return ret;
> }
>
> And processing an i"" is trivial; it is just either a string or a subclass of string (aka a struct with alias toString this) and you'd just use it like that.
>
> The t"" is more composable; it is the superior language feature. But I can live with a convenience compromise.
>
> So we'll see.

Too many features, too much syntax, increases mental overhead. Instead of adding syntax, you can use an existing language feature to do it. For example, t"" could be the default, and it can use alias this to do an automatic conversion of t"" to i"":

struct Tuple {
    private string toString();
    alias toString this;
};

I don't know how using alias this in this way would change compilation time to  relatively efficient (=efficient enough to test with) machine code.
September 12, 2020
On 9/12/20 9:44 AM, Paul Backus wrote:
> On Saturday, 12 September 2020 at 12:37:14 UTC, Andrei Alexandrescu wrote:
>> On 9/11/20 5:36 PM, Stefan Koch wrote:
>>>
>>> could be a compiler tuple which doesn't need std nor object.d.
>>
>> Shouldn't because it needs to be expandable on demand, not implicitly.
> 
> The only way I can think of to do this that works in the general case is something like the following:
> 
> // Before
> writeln(i"Hello $name!".expand);
> 
> // After
> template Pack(Args...)
> {
>      alias expand = Args;
> }

Affirmative. We have that already: https://dlang.org/library/std/typecons/tuple.expand.html

A dead simple Pack would have a good place in druntime and have Tuple be an elaboration thereof.

> auto ref __interpexpr1() { return name; }
> 
> writeln(Pack!("Hello ", __interpexpr1, "!").expand);
> 
> The reason you can't use a struct (that is, a "run=time tuple") is that the mapping from *expressions* to *values* is not injective--it discards information about ref-ness and lazy-ness (and maybe others I haven't thought of?). And the reason you have to "quote" each expression by wrapping it in a function is that template argument lists only accept symbols, not expressions.
> 
> I'm not sure if I like this better or worse than DIP 1027's "naked argument list" approach.

I'd say don't complicate with that. Copy everything into the tuple. When one reaches for interpolated strings, it's not like they're hoping for a speed demon. Okay to draw the line at @nogc.
September 12, 2020
On 9/12/20 10:37 AM, James Lu wrote:
> On Saturday, 12 September 2020 at 02:48:38 UTC, Adam D. Ruppe wrote:
>> On Friday, 11 September 2020 at 20:46:05 UTC, Paul Backus wrote:
>>> This solves the issue of accidentally passing the wrong thing with i"Window $id", and also prevents non-interpolation-related accidental usage, like mixing up the width and height.
>>
>> yeah that's legit.
>>
>>
>> So what we're considering is simplifying it a bit and dropping the embeddable format strings. Also Steven is seeing if he can make auto-conversion work and I'm mulling over your idea of two different prefixes. t"..." yields the tuple, i"..." automatically calls idup (or whatever). t is the building block, i is the "just give me a string" shortcut built on top of t.
>>
>> So in my next draft, processing a t"" yourself looks like:
>>
>> auto foo(InterpList, Args...)(InterpList interp, Args args) {
>>     string ret;
>>     foreach(idx, arg; args) {
>>         ret ~= interp.strings[idx];
>>         ret ~= to!string(arg);
>>     }
>>     ret ~= interp.strings[args.length];
>>     return ret;
>> }
>>
>> And processing an i"" is trivial; it is just either a string or a subclass of string (aka a struct with alias toString this) and you'd just use it like that.
>>
>> The t"" is more composable; it is the superior language feature. But I can live with a convenience compromise.
>>
>> So we'll see.
> 
> Too many features, too much syntax, increases mental overhead. Instead of adding syntax, you can use an existing language feature to do it. For example, t"" could be the default, and it can use alias this to do an automatic conversion of t"" to i"":
> 
> struct Tuple {
>      private string toString();
>      alias toString this;
> };
> 
> I don't know how using alias this in this way would change compilation time to  relatively efficient (=efficient enough to test with) machine code.

I think it's telling that now it's not only about adding two new tokens to the language, but about a synthetic subtyping relationship between them. How can this pass the laughing test?
September 12, 2020
On Saturday, 12 September 2020 at 14:37:45 UTC, James Lu wrote:
> Instead of adding syntax, you can use an existing language feature to do it.

That's basically the C# solution.

That is good if we just doing simple values, but it fails for D's unique compile-time things and is iffy with ref and non-copyable types.

I wrote about it in more detail in my blog last year:

http://dpldocs.info/this-week-in-d/Blog.Posted_2019_05_13.html#hybrid-library-solutions

In short, things like `ref`, `enum`, and `alias`-ness of data are lost through that layer.

So good, but not great because it doesn't build on D's other existing strengths.



Me and Steven continue to argue in a chat btw, we're whittling each other's ideas down and we're coming to something you all will prolly like...

so stay tuned.
September 12, 2020
On 9/12/20 9:11 AM, Adam D. Ruppe wrote:
> On Saturday, 12 September 2020 at 12:40:21 UTC, Andrei Alexandrescu wrote:
>> I am legitimately scared at this point.
> 
> Posts like this add nothing of value to the conversation. You should at least say why.

The "why" is in subtext. Apologies if not obvious. It was along the lines of:

"Great, so this language feature already wants to serve too many masters. Now we have it spawning Sorcerer-Apprentice style. The ultimate Deus Ex Machina of language design ever: yet another syntactical addition. A tool to be reached for with the highest trepidation, now mentioned glibly. I am afraid. I am very afraid."

> But you have to understand there is literally no winning. Provide a convenience feature and people complain it is not composable. Provide a composable feature and people complain it is not convenient. Provide both and get this.

At this point I think a win would be to reject this DIP. I'd rather have no interpolation than live with this little monster.

> At a certain point, we'll have to tell one group (or more) "sorry, you lose". Personally, I say we should make it composable and tell everyone else to suck it up and call a function on the result. But I'm trying to be a team player here and at least explore the options before dismissing them.

There may be the opposite view, in which the community tells you to give up on this or that or the other facility. It seems to me that that's the best mental frame for a DIP writer.

There is also a matter of being able to disagree strongly on something without that spilling into the personal. (Something my wife and I very much want to do in our own disagreements, with limited but notable success.) You and I work together. Steve and I are neighbors of sorts. I should be able to look you two in the eye and tell you, "this design sucks". And you should be able to tell me (hopefully not in retaliation), "autodecoding sucks". And we should all enjoy a drink of our choice together same as before.