December 12, 2019
On Thursday, 12 December 2019 at 17:19:35 UTC, H. S. Teoh wrote:

> Wut...?!  The primary reason I'm using D is *because* of metaprogramming features.  It's one of the things about D that stands out above other languages and differentiates it from them.  For me, it's one of the important things that make it worth using D in spite of whatever other flaws D may have.

You're not the average programmer considering using D. You've got years of experience with D, and probably C and C++ as well. Metaprogramming has its place. You can definitely overdo it though, making your code hard to read and driving folks to other languages. Take a look at the use of templates. Do they have a place? Sure. But one person after another also complains about the difficult of learning the standard library because of the incredible overhead.

I feel I have to keep bringing this up, because at least around here, there are very few concerns for new users that just want to write code.
December 12, 2019
On Thursday, 12 December 2019 at 10:33:21 UTC, aliak wrote:
> So the interpolated dip thread got me thinking, and wondering if any time there's been a proposal for an opMixin? It can possibly be the hash tag symbol? And opMixin does what mixin does, and mixes the code in the spot.

Maybe (ab)use opDollar?

> auto html = json$q{ // compile error if invalid json
>   "hello": "${variable}",
>   "another: "${a + b}",
> };



December 12, 2019
On Thursday, 12 December 2019 at 17:59:25 UTC, bachmeier wrote:
> I feel I have to keep bringing this up, because at least around here, there are very few concerns for new users that just want to write code.

Yes, but I think the solution is to create a language separation between library code and application code.

That would force library authors to write APIs that does not require advanced syntax, but could still use advanced features internally.
December 12, 2019
On Thursday, 12 December 2019 at 17:26:19 UTC, jmh530 wrote:
> The idea for the convenience operator is discussed on the DIP 1027 thread [1] by Paul Backus (though he uses @ and I'm a bit more sympathetic to your #). The way he describes it is just a simple re-write of
> writeln(@interp!"The number ${num} doubled is ${num * 2}!"));
> to
> writeln(mixin(interp!"The number ${num} doubled is ${num * 2}!"));
>
> I find it an interesting idea, but wonder what the consequences of this are more generally.

I managed to find the source for this idea: it's a Github comment by Nick Treleaven on an earlier string interpolation DIP.

    https://github.com/dlang/DIPs/pull/140#pullrequestreview-212264577

Personally, I prefer this rewriting approach to something like opMixin because it doesn't require you to declare a struct as boilerplate, and it works "out of the box" for both templates and CTFE, as well as "naked" strings:

    #foo!(args) => mixin(foo!args)
    #foo(args)  => mixin(foo(args))
    #someCode   => mixin(someCode)
December 12, 2019
On Thursday, 12 December 2019 at 18:24:30 UTC, Paul Backus wrote:
> Personally, I prefer this rewriting approach to something like opMixin because it doesn't require you to declare a struct as boilerplate, and it works "out of the box" for both templates and CTFE, as well as "naked" strings:
>
>     #foo!(args) => mixin(foo!args)
>     #foo(args)  => mixin(foo(args))
>     #someCode   => mixin(someCode)

It is too noisy for formatting. Also, too hard for newbies to use, they will misapply it and get weird errors.

You need a type check on the library type to ensure that it has been designed for mixin. (Mixin should not exist on the application level.)

December 12, 2019
On Thursday, 12 December 2019 at 18:35:03 UTC, Ola Fosheim Grøstad wrote:
> It is too noisy for formatting. Also, too hard for newbies to use, they will misapply it and get weird errors.

I don't think it's any harder to use than the `mixin` keyword, though I'll concede that it's more cryptic to read and harder to search for in the documentation.

On the other hand, I think both of those arguments also apply to opMixin. Newbies are not likely to have an easy time understanding the difference between `foo!(args)` and `foo#(args)`. (After all, they already get tripped up by the difference between `foo(args)` and `foo!(args)`.)

> You need a type check on the library type to ensure that it has been designed for mixin. (Mixin should not exist on the application level.)

I'm not sure I understand what you mean. The only type you can mix in is `string`. There's no "library type" involved at all. Even the original "interpolator" example is really just a template function that takes a string as a compile-time argument and returns another string.

Are you proposing a language-level distinction between "string that contains D code for mixing in" and "string that contains some other kind of data"? I can see how that would be a useful thing to have, though it strikes me as orthogonal to the discussion in this thread--all uses of string mixins would benefit from it equally.
December 12, 2019
On Thursday, 12 December 2019 at 19:08:40 UTC, Paul Backus wrote:
> I don't think it's any harder to use than the `mixin` keyword, though I'll concede that it's more cryptic to read and harder to search for in the documentation.

I think a solution for string interpolation has to be very close to what other languages offer, maybe it would have to be made a special case for strings.

> On the other hand, I think both of those arguments also apply to opMixin. Newbies are not likely to have an easy time understanding the difference between `foo!(args)` and `foo#(args)`. (After all, they already get tripped up by the difference between `foo(args)` and `foo!(args)`.)

Yes, I agree.

If you specialcase mixin-providers that only take one string parameter, then it is possible to come up with a protocol, that can provide something that is "fool proof" and simple syntax:

   f#"..."       $f"..."      f«...»     f!!"…"       f"""…"""

The compiler type checks the variable f for satisfying a string-interpolation protocol. And it is only allowed to return a mixin string that generates a pure lambda function with const parameters and some other constraints. Could even constrain the lambda to return a string or tuple.

> Are you proposing a language-level distinction between "string that contains D code for mixing in" and "string that contains some other kind of data"?

Yes, I guess it would be possible to type a mixin-string in such a way that it is only allowed to represent a lambda function that is being called. As in typing the string to a function signature, would be one step.

Maybe it can be expressed in D code already.

Probably not enough, but one step.

December 12, 2019
On Thursday, 12 December 2019 at 19:08:40 UTC, Paul Backus wrote:
> On Thursday, 12 December 2019 at 18:35:03 UTC, Ola Fosheim Grøstad wrote:
>> It is too noisy for formatting. Also, too hard for newbies to use, they will misapply it and get weird errors.
>
> I don't think it's any harder to use than the `mixin` keyword, though I'll concede that it's more cryptic to read and harder to search for in the documentation.
>
[snip]

One thing I would be worried about is

instead of
string s = "int y;";
mixin(s);

someone would do
string s = "int y;";
#s;
...
//some point later
y++;

and then try to debug that if something goes wrong.

So would you do this for both mixin expressions and statements?

I feel like limiting it to mixin expressions might actually make some of the risk of cryptic stuff happening a little less.
December 12, 2019
On Thursday, 12 December 2019 at 19:42:59 UTC, Ola Fosheim Grøstad wrote:
> On Thursday, 12 December 2019 at 19:08:40 UTC, Paul Backus wrote:
>> I don't think it's any harder to use than the `mixin` keyword, though I'll concede that it's more cryptic to read and harder to search for in the documentation.
>
> I think a solution for string interpolation has to be very close to what other languages offer, maybe it would have to be made a special case for strings.

I agree. Personally, I'm a fan of Adam Ruppe's proposal.

A mixin operator would have applications beyond just string interpolation, though. For example, it could make pattern matching a bit more palatable:

    a[i .. j].match!(
        #pattern!`[] => false`,
        #pattern!`[xs...] => search(xs, target)`
    );

>> Are you proposing a language-level distinction between "string that contains D code for mixing in" and "string that contains some other kind of data"?
>
> Yes, I guess it would be possible to type a mixin-string in such a way that it is only allowed to represent a lambda function that is being called. As in typing the string to a function signature, would be one step.

Is there any actual difference between mixing in a bare expression vs. an immediately-called lambda function that evaluates to the same expression? Forcing string mixins to represent lambdas in particular seems needlessly restrictive.
December 12, 2019
On Thursday, 12 December 2019 at 21:40:33 UTC, Paul Backus wrote:
> Is there any actual difference between mixing in a bare expression vs. an immediately-called lambda function that evaluates to the same expression? Forcing string mixins to represent lambdas in particular seems needlessly restrictive.

The idea is to prevent writing to variables outside the mixin. So, @pure and const params would perhaps be enough to enable that?