Where are we with thoughts on string interpolation and mixins?

Nicholas Wilson iamthewilsonator at hotmail.com
Tue Nov 20 10:16:11 UTC 2018


On Tuesday, 20 November 2018 at 09:19:41 UTC, aliak wrote:
> Hello,
>
> I do a lot of work with mixins. But, it's usually very hard to 
> read, and therefore reason about, and therefor review, and 
> therefor maintain. So I'm wondering what people's thoughts are 
> on how we can improve the experience of using mixins.
>
> I'm thinking two things:
> 1) String interpolation
> 2) mixin syntax (this is not as big a deal as 1 IMO)
>
> I was triggered by this in rust: 
> https://github.com/bodil/typed-html - not completely relevant 
> but it made me think: "oh, that's really nice and readable" and 
> then I thought of D mixins and felt sad.
>
> I'm referring to (this is plucked form random projects on 
> github) code like this:
>
> template MPQ_F_GET(char[] type, char[] name, char[] name2 = 
> name) {
>     const char[] MPQ_F_GET = type ~ " " ~ name2 ~ "() { " ~
>             type ~ " ret; " ~
>             "file_" ~ name ~ "(am, fileno, &ret); " ~
>             "return ret;" ~
>         "}";
> }
>
> Which, frankly, I had no idea what it was doing till I 
> transformed it to this:
>
> template MPQ_F_GET(char[] type, char[] name, char[] name2 = 
> name) {
>     const char[] MPQ_F_GET = q{
>         $type $name2() {
>             $type ret;
>             file_$name(am, fileno, &ret);
>             return ret;
>         }
>     };
> }
>
> Then I realized, ok, it's creating a function. Before that, I 
> didn't see the "()" because it was hidden in noise. I was 
> confused about "ret" because I assumed the mixin was generated 
> from the template parameters. And I had no idea "file_" ~ name 
> ~ "(am, fileno, &ret); " ~ was a function call O_o. Here's 
> another one:
>
> private char[] bindCode( char[] symbol ) {
>    return symbol ~ " = cast( typeof( " ~ symbol ~
>       " ) )m_sLibrary.getSymbol( `" ~ symbol ~ "` );";
> }
>
> As opposed to:
>
> private char[] bindCode( char[] symbol ) {
>    return q{
>        $symbol = 
> cast(typeof($symbol)m_sLibrary.getSymbol($symbol);
>    };
> }
>
> And here's a one liner:
>
> mixin("self."~option.VarName ~ " = " ~ "assumedValue.to!bool;");
>
> mixin("self.${option.VarName} = ${assumedValue.to!bool};");
>
> I've found that you waste A LOT of time just trying to figure 
> out where ~ and " or ` go when you're writing a mixin. And 
> don't even get me started on this pattern: `"` ~var ~ `";`; The 
> number of times I've had a bug there and been thinking ... "why 
> does this not compile" ... "ooooh a missing semicolon"...
>
> This:
>
> `"`~x`"~`~"` ~var ~ `";`;
>
> As opposed to this:
>
> `"$x" ~= "$var"`;
>
> The difference to someone coming from interpolated strings land 
> is quite significant. For people used to mixins, it's maybe 
> less so? I'm not sure. I feel the pain everytime I try and 
> mixin some code.
>
> And I feel like this is almost like asking people to move to a 
> ranged for loop because the C for(;;) is just inferior in 
> readability, maintainability, debuggability, and reviewability 
> ... which is basically time, money, sanity, developer 
> satisfaction, etc, etc. But at the same time, the C for-loop 
> works "just fine".
>
> I tried to rewrite this one as well [0], because I think that 
> could look/read much better with interpolated string, but I 
> couldn't understand it because there was just too much noise 
> and my head hurt and I gave up and I threw my mac out the 
> window and then I dissolved in to the virtual ether and wrote 
> this post in my now new binary, and starved, form.
>
> If it makes a difference at all as well, I've gotten this look 
> at work 🤨when I say, yeah, there's no string interpolation in 
> this language. And also "how old is this language?"
>
> Ok, so now for the mixin syntax:
>
> mixin(function("blah"));
>
> What're thoughts on something like template mixin syntax so 
> that we can get rid of those extra parens?:
>
> mixin function("blah");
>
> I couldn't really think of anything other than that or to allow 
> for a trailing mixin decleration, i.e.: function("blah").mixin;
>
> Thoughts?
>
> Cheers,
> - Ali
>
> PS: I know that there're dub packages, but they a) they add yet 
> another layer of indent, yet another set of parens or a bang, 
> b) more uses of mixin (i.e. - mixin(mixin s!`"$x" ~= "$var"`"); 
> - erm, I'm not even sure if that'd work, and c) take up a 
> symbol which adds the friction of having to alias it away to 
> something both nice, and unoccupied in your that particular 
> file. Which also, btw, adds a maintainability nightmare and a 
> code review nightmare - "wait what, interpolation is 'i' here 
> but 'interp' in this file? And 's' in this other file??? - no 
> thanks". Plus, dependencies for quick scripts are just 
> overkill, and then you just go and use python instead.
>
> PPS: I also believe that string interpolation was one of the 
> top requested things in the survey this year? I may be 
> misremembering though.
>
> [0]: 
> https://github.com/atilaneves/unencumbered/blob/7ecc9a811268edd6170bd294ac846d4da72acc8a/source/cucumber/reflection.d#L86

Perhaps not too well known, mixin now supports multiple arguments 
of any type like pragma(msg) does and stringises each arg. So 
returning an AliasSeq of the fragments should be passable 
straight to mixin.


More information about the Digitalmars-d mailing list