February 05, 2020
On Wednesday, 5 February 2020 at 10:46:11 UTC, Paolo Invernizzi wrote:
> String interpolation is not solving anything that needs to be solved

Readability is a moving target, and a subjective one as well. A lot programmers I have worked with find string interpolation to reduce the ugly-ness of their code, and I completely agree with them.

To me that means it is a feature worth having.

On top of that string interpolation can be used for DSL work, something D is well suited for, as well as for string mixins.
February 05, 2020
On Wednesday, 5 February 2020 at 11:15:35 UTC, FeepingCreature wrote:
> On Wednesday, 5 February 2020 at 10:46:11 UTC, Paolo Invernizzi wrote:
>> String interpolation is not solving anything that needs to be solved, as a consequence, I don't want another 'convenient' feature added if it's not super-easy to grasp and use.
>>
>> /P
>
> I mean, define "needs to be solved"? Strictly speaking, once you have any Turing complete language, no language developed other is doing something that needs to be solved. What standard do you have for D feature development?

I don't think it's pertinent to this discussion thread, nor adding nothing, so I would not go dip in that.

> String interpolation is something that many people wish D had. (See the survey.) Why is that insufficient?

Because it's suboptimal, and not trivial to grasp and use, like in other languages.


February 05, 2020
On Wednesday, 5 February 2020 at 11:24:46 UTC, Sebastiaan Koppe wrote:
> On Wednesday, 5 February 2020 at 10:46:11 UTC, Paolo Invernizzi wrote:
>> String interpolation is not solving anything that needs to be solved
>
> Readability is a moving target, and a subjective one as well. A lot programmers I have worked with find string interpolation to reduce the ugly-ness of their code, and I completely agree with them.
>
> To me that means it is a feature worth having.

I agree with you, I use string interpolation all the time, in python, or javascript for example

> On top of that string interpolation can be used for DSL work, something D is well suited for, as well as for string mixins.

That's fine, I'm doing SQL parsing in D, so definitely that would help.

The all point is that, simply, IMHO, with that DIP in place, I would stick with business-as-usual, and go with the standard way of writing `bla %s foo %d`.format(bar, baz).

A different beast is Adam / Steven proposal ... but to this one, my vote will be -1.






February 05, 2020
On Wed, Feb 05, 2020 at 11:38:58AM +0000, Paolo Invernizzi via Digitalmars-d wrote: [...]
> A different beast is Adam / Steven proposal ... but to this one, my vote will be -1.
[...]

I agree. I would also vote -1 for this proposal. It's an anemic implementation of string interpolation that neither hits the target of what most people expect string interpolation to be, nor adds any new value that makes up for this lack. It's bringing a knife to a gunfight.

Adam/Steven's proposal is *so* much better, in that it meets most people's expectations (the interpolated string implicitly convertible to string), *and* enables powerful use cases other languages can't even dream of (type-checked SQL generation, etc). It's bringing a gun to a knife fight. :-D


T

-- 
Which is worse: ignorance or apathy? Who knows? Who cares? -- Erich Schubert
February 05, 2020
On Wednesday, 5 February 2020 at 11:51:00 UTC, H. S. Teoh wrote:
> On Wed, Feb 05, 2020 at 11:38:58AM +0000, Paolo Invernizzi via Digitalmars-d wrote: [...]
>> A different beast is Adam / Steven proposal ... but to this one, my vote will be -1.
> [...]
>
> I agree. I would also vote -1 for this proposal. It's an anemic implementation of string interpolation that neither hits the target of what most people expect string interpolation to be, nor adds any new value that makes up for this lack. It's bringing a knife to a gunfight.
>
> Adam/Steven's proposal is *so* much better, in that it meets most people's expectations (the interpolated string implicitly convertible to string), *and* enables powerful use cases other languages can't even dream of (type-checked SQL generation, etc). It's bringing a gun to a knife fight. :-D
>
>
> T

Exactly my opinion. I also vote -1 and hope we can get instead the proposal from Adam / Steven.

Kind regards
Andre
February 05, 2020
On Wednesday, 5 February 2020 at 11:51:00 UTC, H. S. Teoh wrote:
> the interpolated string implicitly convertible to string)

That's actually not true. It will not implicitly convert because it is still a tuple. The first element is a struct with `alias this`, but I still recommend AGAINST that implicitly converting to avoid the `createWindow` problem described here: https://gist.github.com/adamdruppe/a58f097d974b364ae1cbc8c050dd9a3f#wrong-use-in-unrelated-function

However, I did allow it to implicitly convert to `const(char)*` (actually it prolly should be immutable, but meh) for purposes like `printf`, but if and only if you specify formatters for every item in the string. See: https://gist.github.com/adamdruppe/a58f097d974b364ae1cbc8c050dd9a3f#on-implicit-conversions

Instead of implicitly converting, you get a type error. I recommend the compiler special-case the type error to point users toward a web page explaining their options, one of which is an overload of `idup` in object.d https://gist.github.com/adamdruppe/a58f097d974b364ae1cbc8c050dd9a3f#diagnostics

This, I feel, is the best compromise between our opposing wishes as a diverse community:

1) It prevents common mistakes while still allowing some flexibility with legacy functions. You still *can* call `printf` incorrectly, but the short, convenient syntax will not allow it. This means you are less likely to accidentally send it on a wild pointer chase.

I personally think error checking is very important. D should not make the wrong thing easy.

2) It makes GC allocations explicit, yet convenient, with my proposed `idup` overload. If you just want to do

string s = i"whatever";

it will error and then you just slap `.idup` at the end, same as if you were assigning from a const char[] without worrying about performance details.

D users are no strangers to explicit extra calls for performance. See also: `.array` on ranges. People get used to it, then hopefully later learn why it does this and there can be better alternatives!

But here to be friendly to new users, I do want the special error message in the compiler telling people what they can do and why via web link. We do special error messages for `writeln` import missing for the same reason.

At the same time, D is supposed to be easy and many of us are perfectly OK with random GC allocations... and the .idup solution is close enough at very little - though admittably not zero - effort.

3) It makes other advanced uses range from very easy (if the library author utilizes the overload) to possible (user might need to specify strings or call other helper functions or write their own function depending on the exact circumstance).
February 05, 2020
On Wednesday, 5 February 2020 at 13:26:13 UTC, Adam D. Ruppe wrote:
> This, I feel, is the best compromise between our opposing wishes as a diverse community:
> [snip]

The implementation specified here is, more or less, what I would actually want out of string interpolation in D.

The original DIP seems like it'd be way too easy to shoot yourself in the foot with if you tried to use it for anything other than printf/writefln.
February 05, 2020
On 2/5/20 1:07 AM, Walter Bright wrote:

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

I want to respond to this point because I feel you have misunderstood the point of my rationale in the modification I proposed.

I do NOT want the compiler (or the runtime) escaping anything. I want everything to go in as-is.

However, the function which is called with this information CAN treat it differently if desired. For example (and this is just an example, not a requirement or expectation), we could pretty much make the `f` versions of write obsolete, as having the formatting done by string interpolation can simply be put into the non-f versions.

Example:

writeln(i"your hex data is ${%02x}someByte");

There's no need for the 'f' version of writeln there if the interpolated string format is not just a basic string, and recognized specially by writeln. Not only that, but if you did need to put interpolated strings later in the parameter list (which would now be possible), the "just slap a format at the end" is a horrible alternative, because it means you are allocating a string just to print stuff. This is providing more efficient code.

AS A BENEFIT, in this instance, writeln can simply ignore any % that is in the string part of the format string in terms of a formatting specifier. This is so much cleaner, as 1) no matching of format specifiers to parameters need take place, the compiler has already done that work, and 2) the code actually doesn't have to parse the non-format parts of the format string AT ALL.

In other words, I don't want the compiler or runtime knowing ANYTHING about formatting or the specific formatting specifiers required for formatting strings for any call (thank you for making that possible by passing the format specifier as-is). I just want it to be POSSIBLE to treat that differently than "all % in the first parameter are meaningful".

I LIKE the DIP in that it gives you instant compatibility with existing format + args calls. That's its hallmark feature. I wouldn't want to change that, as instantly, you can start using it with all your code base with just cleaner-looking calls. But IMO we can and should do better to allow library writers the benefit of the compiler's knowledge.

> ----
> 
> 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.

The additional proposal isn't any less minimalist. All you are doing is transforming the format specification into a tuple instead of a string. I bet the code isn't even any more complicated.

When I think about existing D features, to me the additional proposal is akin to the transition from opAdd, opMul, opSub, etc to opBinary!(string op). The power realized there can be realized here as well. The more things you give people to play with at compile time, the more efficient the code can be, the more specialized people can do things.

Consider this -- we can do compile-time checking of format strings outside the compiler with this feature at any later time. Again, with minimal effort, as parsing the format string for valid % tokens isn't necessary.

-Steve
February 05, 2020
On 2/5/20 4:15 AM, Johannes Loher wrote:
> On Wednesday, 5 February 2020 at 06:48:43 UTC, Arine wrote:
>>
>>     string v = i"value = $value";
>>
>> A user isn't going to expect that to be:
>>
>>     string v = ("value = %s", value);
> 
> This still boggles my mind. I know that you can simply write
> 
> string v = i"value = $value".format;
> 
> instead but this is not what anybody who already knows about string interpolation from any other language will expect. It is really weird to have a string syntax (i"") where the result of such an expression is not actually a string (or at the very least implicitly convertible to one).
> 
> Do we really want D to be the odd one out in this case?

I suggested in the first review round [1] that we don't call this "string interpolation" to avoid this confusion (because everyone will just expect this).

But I absolutely think that this is how D should support string interpolation. It's just so much more beneficial than translating to an automatic call to format (note that this WOULD require a library to do it, as the compiler can't possibly know how to string-ify all parameters).

-Steve

[1] https://forum.dlang.org/post/qt8ust$26if$1@digitalmars.com
February 05, 2020
On Wednesday, 5 February 2020 at 09:15:07 UTC, Johannes Loher wrote:
> instead but this is not what anybody who already knows about string interpolation from any other language will expect. It is really weird to have a string syntax (i"") where the result of such an expression is not actually a string (or at the very least implicitly convertible to one).
>
> Do we really want D to be the odd one out in this case?

Yes.

I understand this can be a pain and a bit surprising to new users - which is why my proposal special-cases the compiler error message to explain it - but in exchange for this inconvenience for that case, we gain a lot of benefits:

1) sql(i""); just works, with correct parameterization
2) jsx(i""); just works, with correct contextual encoding
3) writeln(i""); just works
4) printf(i""); can just work
5) Even readf(i""); just works!
6) Error detection is possible - at compile time - for all those scenarios
7) @nogc i"".toBuffer(...) is possible.
8) gettext() style internationalization is possible, including with the D compiler itself collecting the strings!
9) foo!i"" works to collect D aliases so like `my_debug!i"$a and $b"` might give
  a = 5 and b = 3
10) whatever else library authors can dream up!

All this while keeping it type-safe to detect improper or even just inefficient uses.

And, of course, `string s = i"".idup;` is still a very convenient option when you want it, but with so many functions just working, you may want to use them instead of string assignment!

Note that Javascript's template literals allow much of this stuff too and are really cool.


I'm chatting with a user on IRC now who feels this is a dealbreaker to him, it MUST implicitly convert. But the next best proposal for implicit conversion loses benefits #4 and #5 there (which I argued earlier in this thread was worth it!), makes #6 still possible but less generally applicable, and makes #7 and #9 pretty iffy. So I think `.idup` is an OK trade off here.

Like Steven, I encourage you all to look at i"" not being an interpolated string per se, but being a "string builder literal" or something like that - it is syntax sugar that gives an entity you can get a string out of rather than a string itself. An interpolated string is just one of the *many* things you can build with this new literal, and I expect that once you use it with some cool library support, you'll agree the explicit `idup` in some cases - and that's all you have to do to get the plain GC string out of it, no import necessary for that case in my proposal - is worth the gains we get in all these other cases too.