On Sunday, 20 August 2017 at 19:27:43 UTC, WhatMeWorry wrote:

It's stuff like this which makes me very frustrated. Or depressed because it demonstrates just how poor a programmer I am:


string printStatement(string message) {
    return `writeln("` ~ message ~ `");`;
}

void main()
{
// Mixins are for mixing in generated code into the source code.
    // The mixed in code may be generated as a template instance
    // or a string.

    mixin(printStatement("hello world"));
    mixin(`writeln(` ~ `Hello`  ~ `);` );
    mixin("writeln(`World`);");       
}

Compiling gives me the errors:

Error: undefined identifier Hello

To me, `writeln(` ~ `Hello` ~ `);` is a valid D string? Okay, maybe a
string expression but a string nevertheless.

So, am I giving mixin more magical powers than it possesses?

Should we say that mixin needs to be given a "fully pre-formed D compilable" string?

Thanks. especially to let me vent.


It's not difficult, it's just new. It's not that you are a poor programmer, but you simply have not learned how to think about mixins correctly. Stop whining about it and focus that energy on working with them.

String mixins are very simple. It takes any string and inserts it as code in to the program directly as if you typed it by hand.

What makes them useful is that you can build strings a compile time and so essentially introduce compile time code generation.

e.g.,

L324: mixin("Hello World")

becomes

L324: Hello World

and so

mixin(N)

gets inserted as

N, as if you typed it in directly. (this is the important part. N isn't inserted but the contents of N as a string.

What this is good for, is say you want to generate code based off stuff at compile time, e.g., a configuration file. You can generate valid D code using strings that load the configuration file at compile time and do what you want with it.

e.g.,

enum config = import(myconfigfile);

config now contains, as a string, the contents of myconfigfile AT COMPILE TIME. Normally we think of config as being a run time variable, but it is simply a compile time variable(well, it can't vary, unfortunately, the compile time processing is not a fully integrated compile time compiler.

enum configCode = process(config);

let process be a function that takes config, extracts the data from it and bundles it all up in new D code.

mixin(configCode);

Now mixes in that code direct in to the source as if we typed it.

e.g.,

enum classes = import("classNames");
string code;
foreach(n; classes.split(","))
   code ~= "class "~n~";\n";
// at this point code should be something like "class X;\nclass Y;" etc, but it depends on the file.
mixin(code);

has the same effect if we typed

class X;
class Y;

But the difference is that we used a file to extract the class names and a string mixin that inserted the code. This way we don't have to manually change the class names in our D file, we just change the classNames file, which is probably autogenerated anyways.

String mixins come in very handy when you have D code that can be "generalized" (parameterized).

It's sort of the place holder concept: You have a D string like
"
if (alpha_1 > 0) { Alpha1(); }
if (alpha_2 > 0) { Alpha2();}
if (alpha_3 > 0) { Alpha3();}
if (alpha_4 > 0) { Alpha4();}
"
...

Obviously if you can simplify all that code it would be nice, well you can!

for(int i = 0; i < N; i++)
mixin("if (alpha_"~i~" > 0) { Alpha"~i~"();}");


this will mix N of those lines with the proper mapping. I only have to make one change rather than N.

You have to think of them as D code generators. Of course, you don't have to use them to generate code, but they are insert, foremost, in D code and will be interpreted by the D compiler.

mixin("string X = \"mixin string X = \""mixin string X = \"""mixin string X = .....);

is the same as

string X = \"mixin string X = \""mixin string X = \"""mixin string X = ....."""";

and, if we used enums(compile time object) instead of strings(run time object), we could do

mixin(X); and it would mix in the next layer, which would redfine X each time.

It's not difficult, just requires a different way to think about them, as does anything that is unfamiliar.



















Reply via email to