September 11, 2020
On Friday, 11 September 2020 at 20:04:35 UTC, Andrei Alexandrescu wrote:
>
> Of course the problem is "tuple" is somewhere in std instead of being in object.d.

could be a compiler tuple which doesn't need std nor object.d.
September 11, 2020
On Friday, 11 September 2020 at 16:32:28 UTC, Adam D. Ruppe wrote:
> On Friday, 11 September 2020 at 10:43:54 UTC, Paul Backus wrote:
>> Anyway, I don't expect my idea to satisfy everyone equally.
>
> This right here is why the idup mechanism is how it is.
>
> There's ten cases we identified from various people to try to hit:
>
>  1. string s = i""; should work.
>  2. @nogc use of i"" should be possible.
>  3. foo(i""); should work where it is foo(string) {}
>  4. for createWindow(string s, int width = 0, int height = 0), calling createWindow(i"Connected $id") should NOT result in createWindow("Connected %s", id). It should either error, or convert the entire expression to a string.
>  5. db.query(i""); should be possibly to do safely
>  6. int x; verbose_debug!(i"$x assertion failed"); should be possible
>  7. readf(i"$foo"); should be possible as well as other ref, scope, etc. types
>  8. compile-time checking of format strings should be possible
>  9. mixin(i"T $name;"); should work
> 10. printf(i""); should work
>
>
> Hitting all ten is impossible; some of them are directly contradictory. But if we loosen some of those "should work" things to "works with .idup", then we actually can do them all.

The most critical part of global optimisation is making sure your cost function is good. If you dont account for all the things you want to achieve, and weight them appropriately then you will end up with a sub optimal solution.

IE. In setting those 10 requirements you will pay somewhere else in the design. So the question is are those 10 requirements all thats important? Are they all more important than...

"Is it easy to explain to newbies?"
"Is it easy to use correctly?"
"Will it just work with existing code?"
etc..

Did you account for everything you want in the cost function?

September 11, 2020
On Friday, 11 September 2020 at 22:04:43 UTC, claptrap wrote:
> "Is it easy to explain to newbies?"

I've personally answered ~18% of all D questions on Stack Overflow and while I don't have easily-accessible metrics for the other D help channels, it is likely a similar proportion.

I'm keenly aware that there might be explanations to new users, and I know I'm probably going to be answering about 1/6th of them myself.

Just like I frequently explain why `int[] a = [1,2].map!(a => a*2);` doesn't compile. There's a reason for that, so it is a chance for them to learn something new. Or they can just slap `.array` on it and move on. But if they are willing to learn something new, D opens up a whole new world of possibilities.
September 12, 2020
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.
September 12, 2020
The DIP mentions a problem with DIP1027:

  Window createWindow(string title, int width = 0, int height = 0);

  auto window = createWindow(i"Process debugger $pid");

and the pid value inadvertently being matched to `width`. The DIP says:

  "Without a way to detect this misuse"

There is a way, as the expansion will be:

   createWindow(tuple("Process debugger %s", pid));

and the compiler can warn if a tuple argument precedes a default argument. I do not necessarily agree, however, that this is a problem that needs solving, just that there are ways.
September 12, 2020
On Friday, 11 September 2020 at 20:46:05 UTC, Paul Backus wrote:
> On Friday, 11 September 2020 at 19:59:35 UTC, Adam D. Ruppe wrote:
>> On Friday, 11 September 2020 at 19:31:33 UTC, Paul Backus wrote:
>>> The solution is to use the type system.
>>
>> This is exactly what the DIP does!
>>
>> Something serious must have gotten lost between my brain and the text.
>
> I guess you didn't have time to check out the video. What I mean is, the solution is to change the signature of "createWindow":
>
>     alias Width = Typedef!(int, int.init, "Width");
>     alias Height = Typedef!(int, int.init, "Height");
>
>     void createWindow(string title, Width width, Height height);


Requiring to retype int semantically for every function that has a string followed by an int to avoid “non-obvious” affects of a language feature seems seems a bit overkill.

Pretty sure there was something in Scott meyers talks about APIs that work how you’d expect them to as well.

>
> 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.
>
>> This DIP builds on D's unique strengths, enhancing existing opportunities. None of the others come close, they're just syntax sugar.
>
> I agree with this 100%, except I think it's a point against DIP 1036 and in favor of the other proposals. :)
>
> We already have ways to put stuff in the middle of strings. The reason we want string interpolation is to make the syntax for it less ugly. So, it *should* be "just syntax sugar." Anything beyond that is bloat.


September 12, 2020
On Friday, 11 September 2020 at 18:17:10 UTC, Adam D. Ruppe wrote:
> On Friday, 11 September 2020 at 17:37:36 UTC, SHOO wrote:
>> 2. It doesn't seem to work well with the {} style formatting employed by C#, Rust, etc. Is the following interpretation correct?
>> `String.Format("You are now {0} years old.", years - 1)`
>
> You'd do it more like
>
> `String.Format(i"You are now ${{0}}(years - 1) years old.")`
>
> No backslashes. But it isn't really ideal for positional ones like that since you'd have to keep the count going right yourself.
>
> At this point you would ideally write an overload to String.Format that checks for the interpolation spec then translates.
>
> The DIP's text as submitted right now makes this unnecessarily difficult, so we're gonna reword it. The same implementation still works though.

I understand.

>> 3. The object.idup in the DIP uses `import std.format`, is it permissible for the druntime to be dependent on Phobos?
>
> Technically, druntime is still independent. Since it is a template, its dependency falls on the user, not the library.
>
> When you compile druntime, that code is completely ignored. It is not present in the compiled library and the import is not processed.
>
> If you use the idup function, the instance appears in *your* code and only then is Phobos actually imported. So formally, the dependency is on phobos from your code at the use point. So if you never use it, there's no dependency.
>
> This is one of D's coolest features to me btw.

I am understanding that this is technically possible, but I am still skeptical of this. Whether or not it is technically possible and whether or not it is permissible as a policy are two entirely different things.
idup is part of the druntime. And idup uses std.format.
In general, this would be considered druntime is dependent on std.format.
It appears to be somewhat gray to claim that there is no dependency. I do not recommend doing anything gray.

>> 4. Are there any reasons why backquotes (i`...`) are not allowed?
>
> Trying to just define the simplest thing that can work. D has a lot of string types and adding i to each of them is a lot.... All these cases are possible with the juxtaposition thing though:
>
> i""`....` would work the same way.

If there is no particular negative reason, I think it would be a better DIP to include it. The way i""`....` is written seems redundant.

Also, there is a history of concatenation when multiple string literals are written in succession, which has been previously deprecated. It seems to be a bad idea to adopt a similar method.

>> 5. Although you use the name idup, idup should be used to create `immutable(_d_interpolated_string!Parts)`
>
> There's two pieces to the interpolated tuple: the spec definition and the arguments. The _d_interpolated_string!Parts thing is just the spec definition. So your example is wrong: you left the arguments out. idup makes no sense without combining it.

Sorry, I was wrong. But my point is that converting to another type is the wrong feature of idup.

> The main reason for using idup over toString though is just reusing an existing global name... it won't break any code since it isn't introducing anything new. And since it already works on string it has some precedent:
>
> char[] a;
> string b = a; // cannot convert, you need to idup it.
>
> string b = i"xxx"; // cannot convert, also need to idup it.

The following code will express my point better than above code:

string b = "xxx"w.idup; // cannot implicitly convert expression idup("xxx"w) of type wstring to string
string b = i"xxx".idup; // cannot implicitly convert expression idup(i"xxx") of type ?????? to string
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
>
> 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.
September 12, 2020
On Saturday, 12 September 2020 at 07:49:49 UTC, Aliak wrote:
>
> Requiring to retype int semantically for every function that has a string followed by an int to avoid “non-obvious” affects of a language feature seems seems a bit overkill.

Nobody is required to do anything. My point is, this kind of function is prone to accidental usage *with or without* string interpolation, and making the argument list more strongly typed is an effective technique for fixing that.

Of course, you can also decide that the consequences of accidental usage are not a big deal, and that you're willing to live with them for the sake of convenience. I think that's a totally reasonable decision to make, especially for @safe functions.

Adding additional complexity to string interpolation to compensate for deficiencies in library interfaces is not good design. Problems should be addressed at their source.
September 12, 2020
On 9/11/20 5:36 PM, Stefan Koch wrote:
> On Friday, 11 September 2020 at 20:04:35 UTC, Andrei Alexandrescu wrote:
>>
>> Of course the problem is "tuple" is somewhere in std instead of being in object.d.
> 
> 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.