Re: Mixed up over mixins.

2017-08-21 Thread Johnson via Digitalmars-d-learn

On Monday, 21 August 2017 at 07:34:23 UTC, WhatMeForget wrote:

On Sunday, 20 August 2017 at 22:50:40 UTC, Johnson Jones wrote:

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

[...]



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.


[...]


Thank you.  You have rejuvenated my quest for mixin mastery :)


Just stick with it ;) Things will click. The more you trudge 
through them and just try to immerse yourself in it the faster it 
will happen. I use mixins all the time because they are a great 
way to simplify code... although actually writing them can be a 
pain because you can't debug them in any sane way.


Remember, that you will generally use string generation a ton 
because that is mainly what you are working.


Sometimes, for complex tasks I might have to write a function 
that I run at runtime like a normal program that takes in a 
string and outputs it. This lets me debug properly. As long as 
one doesn't use crazy io(even file IO is blocked ;/) the same 
function can be run at compile time(CTFE).


This means

myfoo("asdfasdf");

will be ran at compile time, the reason is simply that the input 
is constant, there are no side effects, and so the output can be 
computed at compile time.


But the same function can be debugged if ran at runtime... and 
remember, the output is a string, so you can just print it out, 
no mixin is occuring at this point.


The idea is that you make sure the string output is going to be 
the correct D code you want to mixin. It should look like normal 
D code, because if you do a mixin on it, it has to be to compile. 
Any syntax errors will be picked up and you'll be hunting them 
down because D will give you an obtuse error rather than a 
specific line number in the mixin(this is a severe issue with D 
but no one seem to care). If you debugged at runtime, you will 
get a line number where the error occurred, which is why you go 
that route.



Once you've gotten your function written to do the code, you 
simply wrap a mixin() around it, you might have to change a bit 
of runtime to compile time stuff(file io to import) and then all 
that string stuff that you generated becomes D code!


mixin("int i = 3"); <- bug
mixin("int i = 3;"); <- ok

same as

int i = 3;

useless example but sometimes it's helpful. Sometimes to get the 
things working you have to use mixins of mixins:


mixin("mixin("~something~");");

or, take this example

auto alpha = "hello";
mixin("w"~"r"~"i"~"te(`"~alpha~"`);");

before the mixin we have

"w"~"r"~"i"~"te(`"~alpha~"`);"

which, when simplified is

"write(`"~alpha~"`);"

which, since alpha is a constant, we have

"write(`hello`);"

which, the mixin simply does

write(`hello`);

which is now D code.

A mixin, in a sense, just "unstringifies" it's argument and 
inserts it directly in to the source code... it better be valid 
code, which also means the string better be a valid string of D 
code.












Re: Mixed up over mixins.

2017-08-21 Thread Ali Çehreli via Digitalmars-d-learn

On 08/21/2017 12:29 AM, WhatMeForget wrote:

> Thanks. Don't know if you noticed, but i used some code from your book.
> Hope you take that as a complement.

I did notice that and thank you. Every time I see people struggle with 
code that originated from my half-witted examples, I actually feel 
guilty. :)


Ali



Re: Mixed up over mixins.

2017-08-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/21/17 3:29 AM, WhatMeForget wrote:

On Sunday, 20 August 2017 at 19:41:14 UTC, Ali Çehreli wrote:

On 08/20/2017 12:27 PM, WhatMeWorry wrote:

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

Yes, it means that the string must be legal D code.

> mixin(`writeln(` ~ `Hello`  ~ `);` );

Yes, that's a D string but the string itself is not legal D code 
because it would be mixing in the following:


writeln(Hello);

The problem is, there is no Hello defined in the program.

You need to make sure that Hello is a string itself:

writeln("Hello");

So, you need to use the following mixin:

mixin(`writeln(` ~ `"Hello"`  ~ `);` );



Of course, why didn't I "see" that before. I should have slept on it and 
tried again with fresh eyes.  I'm keeping a "beginners journal" on code 
generation.  Maybe write a 101 introduction with lots of samples and 
exercises.


When doing mixins, especially when the code to generate the mixin string 
isn't a simple literal, a great thing to do is to use pragma(msg) to 
show the actual string you are mixing in.


e.g.:
enum mixinstr = ...
pragma(msg, mixinstr);
mixin(mixinstr);

Often times, your error is obvious when you see it that way.

-Steve


Re: Mixed up over mixins.

2017-08-21 Thread WhatMeForget via Digitalmars-d-learn

On Sunday, 20 August 2017 at 22:50:40 UTC, Johnson Jones wrote:

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

[...]



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.


[...]


Thank you.  You have rejuvenated my quest for mixin mastery :)


Re: Mixed up over mixins.

2017-08-21 Thread WhatMeForget via Digitalmars-d-learn

On Sunday, 20 August 2017 at 19:41:14 UTC, Ali Çehreli wrote:

On 08/20/2017 12:27 PM, WhatMeWorry wrote:

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

Yes, it means that the string must be legal D code.

> mixin(`writeln(` ~ `Hello`  ~ `);` );

Yes, that's a D string but the string itself is not legal D 
code because it would be mixing in the following:


writeln(Hello);

The problem is, there is no Hello defined in the program.

You need to make sure that Hello is a string itself:

writeln("Hello");

So, you need to use the following mixin:

mixin(`writeln(` ~ `"Hello"`  ~ `);` );

Ali


Of course, why didn't I "see" that before. I should have slept on 
it and tried again with fresh eyes.  I'm keeping a "beginners 
journal" on code generation.  Maybe write a 101 introduction with 
lots of samples and exercises.


Thanks. Don't know if you noticed, but i used some code from your 
book. Hope you take that as a complement.


Re: Mixed up over mixins.

2017-08-20 Thread Johnson Jones via Digitalmars-d-learn

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.






















Re: Mixed up over mixins.

2017-08-20 Thread Ali Çehreli via Digitalmars-d-learn

On 08/20/2017 12:27 PM, WhatMeWorry wrote:

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

Yes, it means that the string must be legal D code.

> mixin(`writeln(` ~ `Hello`  ~ `);` );

Yes, that's a D string but the string itself is not legal D code because 
it would be mixing in the following:


writeln(Hello);

The problem is, there is no Hello defined in the program.

You need to make sure that Hello is a string itself:

writeln("Hello");

So, you need to use the following mixin:

mixin(`writeln(` ~ `"Hello"`  ~ `);` );

Ali



Mixed up over mixins.

2017-08-20 Thread WhatMeWorry via Digitalmars-d-learn


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.