October 18, 2023
On Wednesday, 18 October 2023 at 22:43:56 UTC, Andrea Fontana wrote:
> I genuinely don't understand the opposition to such a highly desired feature that can only enhance code readability.

Because the parts of the D community that are both vocal and motivated enough to discuss language improvements are a mix of opposing egos striving for their own visions of perfection, and any slight compromise is deemed unacceptable, unworkable, and nothing short of heresy in the eyes of the all mighty Perfect Solution.

I mean this in a relatively sincere way as everyone wants what they think is best for the language, but failure to come to a common ground results in things like several years of on-and-off bike shedding around features other languages (that don't have the same challenges and complications as D for what its worth) could have pushed through several times over since then.

Every C# release I get really excited to see some of the cool new features and syntax sugar they add, as it's often well designed, well integrated, has tooling support straight away, and generally just helps make code feel cleaner... (well not all the time lol).

Meanwhile we still can't figure out a way to get string interpolation into the language that isn't shot dead in its entirety on arrival :D

However if DIP1030 (Named arguments) - which I'm slightly surprise wasn't bikeshedded to rejection - managed to get through, then I'm optimistic in another 5 years we'll have settled on something for interpolation, whether it be outright rejection of the entire idea, or an actual implementable solution.
October 18, 2023
On 10/18/2023 12:53 AM, Alexandru Ermicioi wrote:
> __header is implicitly converted to null string by writeln (the struct will have a toString method that returns null), so from the point of view of existing text methods such as writeln, text, everything is fine.

Ok. So does the user have to define his own InterpolatedExpression to get something different to happen?

October 18, 2023
On 10/18/2023 1:27 PM, Adam D Ruppe wrote:
> On Wednesday, 18 October 2023 at 03:57:52 UTC, Walter Bright wrote:
>> What does writeln() do with __header?
> 
> "The __header value, to be discussed later, is generated by the compiler and contains compile-time information about the interpolated string."
> 
> <a few moments later>
> 
> "The header object has a trivial toString method that expands to the null string. This method makes it possible to pass interpolated strings directly to functions such as writeln and text because these functions detect and use toString to convert unknown data types to strings."
> 
> It just uses the existing rules for a struct. No special case here. It doesn't spell this out, but you can think about what happens to normal D functions if you pass some `struct` to a function expecting a `string` - an ordinary type mismatch error. This is what gives library authors such power with this proposal: they can overload a function to provided specialized behavior.

Ok.

The lowering to arguments to InterpolatedExpression seem to all be string versions of the argument identifiers, rather than what the types are.

"the header gives the callee complete access to the strings corresponding to the expressions passed in."

I don't know what that is useful for. Note that if write() is a template, it already has access to all the arguments and their types.


> Library authors overload functions on the type of what was passed, including an interpolated type if desired, same as any other overload. End users call a particular function uses the given arguments to create their desired result; a generic function forwarder still works, preserving the full interpolated argument, since it works like any other set of function arguments.
> 
> This gives *enormous* capability to both sides - mostly by using already existing features in the D language.

I'd like to see an example of code of how this customization might work, because I don't see it.

P.S. there are several errors in the document, such as '$' appearing in the lowered code. What "normalization" means is unclear.
October 18, 2023
On 10/18/2023 3:43 PM, Andrea Fontana wrote:
> I am less fond of the proposal related to printf/writef/writelnf/format/sformat, etc. It appears to add complexity to the code

Example of the complexity? It's probably the simplest string interpolation I could find.

> introduces unnecessary noise

Example please.

> is prone to errors

It's not prone to errors any more than writef() is, because writef() checks the format against the type of the corresponding argument. As for printf(), we've added format string checking to printf() calls which have virtually eliminated such errors.

October 18, 2023
On 10/17/2023 10:14 PM, Imperatorn wrote:
> Just a quick comment. Probably with string interpolation, less is more.

Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming.

For example, with Ddoc and Unittest, the idea was to go for a simple-as-possible scheme to cover 90%, and it proved to be a winner.

October 19, 2023
On Thursday, 19 October 2023 at 01:12:53 UTC, Walter Bright wrote:
> On 10/17/2023 10:14 PM, Imperatorn wrote:
>> Just a quick comment. Probably with string interpolation, less is more.
>
> Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming.
>
> For example, with Ddoc and Unittest, the idea was to go for a simple-as-possible scheme to cover 90%, and it proved to be a winner.

hmmmmm
I would think its nonlinear and you could easily justify 90 -> 95% being 2x the complexity cost
October 19, 2023
On Thursday, 19 October 2023 at 00:57:35 UTC, Walter Bright wrote:
> The lowering to arguments to InterpolatedExpression seem to all be string versions of the argument identifiers, rather than what the types are.

The types are attached to the parameters themselves, so it is purely redundant to list them again. The interpolated header's job is to preserve the original string, allowing for compile time manipulation of it. The arguments are processed the same as any other `T...` tuple in D.

> "the header gives the callee complete access to the strings corresponding to the expressions passed in."
>
> I don't know what that is useful for. Note that if write() is a template, it already has access to all the arguments and their types.

The strings are not the types. The compiler has this information, the user wrote it, even if you don't see the value, why discard it?

But here's one example: this year's DConf had a talk on gnu gettext. In current D code, they use a template argument string to make a user-defined literal which is collected into the translation files. This is pretty cool. But it loses some information, comments are added by hand:

tr!("One license.", "%d licenses.", Context(“driver's"))(n);

With the interpolation header, it could quite plausibly be:

tr(i"One license.", i"$(driversLicenseCount) licenses.");

(i renamed the variable there because it is now meaningful so you can).

The full string written in the source - i"$(driversLicenseCount) licenses." - is available for inspection. The tr function can even extract that variable name and automatically add it as a comment to the translator, giving them the additional context without needing to write it again in the code.

It also potentially opens up library implementations of something like assert with checkaction=context, showing the original code that led to the result.

Please note that it is just a string in another scope, it is not useful for `mixin` or anything like that. You still inspect the *value* using the argument. But the *string* can be used as a *string* for these other tasks.

> I'd like to see an example of code of how this customization might work, because I don't see it.


Element makeHtmlFromTemplate(T...)(T t) if(T.length && is(T[0] == core.interpolation.InterpolationHeader!Parts, Parts...)) {
    string html;
    foreach(idx, str; Parts) {
      if(idx % 2 == 0)
        html ~= str; // i know this is html string literal thanks to noramlization
      else
       // note i also know what code this came from in case i need it for error messages, debug info, etc, it is in `str`
        html ~= htmlEntitiesEncode(to!string(t[idx / 2]));
    }

    return Element.make(Html(html));
}


auto element = makeHtmlFromTemplate(i`
   <html>
      <p class="foo" title="$(title)">
           $(content)
      </p>
   </html>
`);


Note the VERY important fact that the makeHtmlFromTemplate *knows for a fact* what is html and what is data coming from the outside, so it can be sure about what to encode and what not to.

Also worth noting it has the option of validating the HTML at compile time, using CTFE, because it can reconstruct the string from the InterpolationHeader too - this is a runtime error in most languages, but in D it doesn't have to be.

Javascript can do this kind of thing, with runtime error throwing. The JSX extensions to the language exist to add compile time validation. D ought to be able to do the same thing *without* a custom add-on compiler. We have CTFE.


> P.S. there are several errors in the document, such as '$' appearing in the lowered code. What "normalization" means is unclear.

typos are irrelevant but whatever i'll fix them. "Normalization" means what it says under the "normalization" header, which ensures you can distinctively tell the difference between format string and arguments.
October 19, 2023
On Thursday, 19 October 2023 at 01:12:53 UTC, Walter Bright wrote:
> Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming.

YAIDIP is an incredibly simple solution that has enormous bang for buck.

Its implementation is very simple.
October 19, 2023
On Thursday, 19 October 2023 at 01:12:53 UTC, Walter Bright wrote:
> On 10/17/2023 10:14 PM, Imperatorn wrote:
>> Just a quick comment. Probably with string interpolation, less is more.
>
> Solving for 90% of the cases with a simple solution is preferable than a much more complex one to get a few more %. This is a winning strategy with programming.
>
> For example, with Ddoc and Unittest, the idea was to go for a simple-as-possible scheme to cover 90%, and it proved to be a winner.

Agreed
October 19, 2023
On Thursday, 19 October 2023 at 01:05:59 UTC, Walter Bright wrote:
> On 10/18/2023 3:43 PM, Andrea Fontana wrote:
>> I am less fond of the proposal related to printf/writef/writelnf/format/sformat, etc. It appears to add complexity to the code
>
> Example of the complexity? It's probably the simplest string interpolation I could find.
>
> > introduces unnecessary noise
>
> Example please.

For example:

```
string t = format(i"...."));
           ^^^^^^
```

>
> > is prone to errors

Well, you know, even you posted a wrong example earlier in the thread.

I'm also somewhat concerned about potential error messages that might confuse users due to the non-obvious abstraction: f.e. what happens if someone writes ```myfunction(i"hello $name!");```

Andrea