www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template mixin Instantiation

reply Jorge Lima <jmalima69 gmail.com> writes:
Can someone explain me why in the following code the alias 
parameter expands differently for first and second Instantiation?

module main;
import std.stdio;
import std.conv;

struct Cascade {
     this(int a, immutable(Cascade)[] b)
     {
         f1 = a;
         f2 = b;
     }
     this(int a)
     {
         f1 = a;
         f2 = null;
     }
     int f1;
     immutable(Cascade)[] f2;
}

immutable Cascade [] array1 = [
     Cascade(1),
     Cascade(2),
     Cascade(3),
     Cascade(3)
];

mixin template StaticArr(alias a) {
     immutable(typeof(a[0]))[a.length] array = a;
     string repr = a.stringof;
     void printIt()
     {
         writeln(repr);
     }
}

int main()
{
     mixin StaticArr!(array1) x;
     mixin StaticArr!([
         Cascade(10),
         Cascade(20, array1)]) y;

     x.printIt();
     y.printIt();

     return 0;
}

Running the program prints:
array1
[Cascade(10, null), Cascade(20, [Cascade(1, null), Cascade(2, 
null), Cascade(3,
null), Cascade(3, null)])]

I can understand that array1 is not expanded to its value 
representation in the first call, but why is then when passed as 
an argument to the Constructor of the literal argument in the 
second call? Am I missing something obvious?

Thanks,
Jorge
May 25 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 25 May 2016 at 07:45:32 UTC, Jorge Lima wrote:
 I can understand that array1 is not expanded to its value 
 representation in the first call, but why is then when passed 
 as an argument to the Constructor of the literal argument in 
 the second call? Am I missing something obvious?
It is just the difference between an alias argument and an ordinary value use. When passing a name to an alias argument, it retains its identity - `a` in there is now just another name for `array1`. When you `.stringof` it, it sees `a` is an alias for `array1` and pulls it instead. I suspect you don't actually mean `.stringof` here... that gives the string representation of the identifier; it is what you see in the source (sort of), not the string of the value. `writeln(array)` would make it print out the value of the array. Anyway, if you pass `a` to an ordinary function, like the struct constructor, it is then interpreted as a value instead of as a name of a variable and works the same way as the literal. The difference is just on the outside, you aliased a name in one place and a literal in the other place, so that's why .stringof gave different results.
May 25 2016
parent Jorge Lima <jmalima69 gmail.com> writes:
Hi Adam,

Thanks for your explanation.

On Wednesday, 25 May 2016 at 12:15:17 UTC, Adam D. Ruppe wrote:
 On Wednesday, 25 May 2016 at 07:45:32 UTC, Jorge Lima wrote:
 I can understand that array1 is not expanded to its value 
 representation in the first call, but why is then when passed 
 as an argument to the Constructor of the literal argument in 
 the second call? Am I missing something obvious?
It is just the difference between an alias argument and an ordinary value use. When passing a name to an alias argument, it retains its identity - `a` in there is now just another name for `array1`. When you `.stringof` it, it sees `a` is an alias for `array1` and pulls it instead.
That part I can somehow grasp.
 I suspect you don't actually mean `.stringof` here... that 
 gives the string representation of the identifier; it is what 
 you see in the source (sort of), not the string of the value. 
 `writeln(array)` would make it print out the value of the array.
No, my intention was not to print the value of the array. Instead, in order to understand mixin template mechanism, I was trying to inspect the code generated at the instantiation. I thought .stringof would be the way to get it. But I'm also not sure about it.
 Anyway, if you pass `a` to an ordinary function, like the 
 struct constructor, it is then interpreted as a value instead 
 of as a name of a variable and works the same way as the 
 literal.
I understand the difference between a normal parameter and a alias parameter in a mixin template. But shouldn't any replacement occur after the code being generated? Assuming that .stringof has anything to do with the code generated.
 The difference is just on the outside, you aliased a name in 
 one place and a literal in the other place, so that's why 
 .stringof gave different results.
Then, if I understand correctly, what you are saying is that array1 in the second instantiation gets replaced by its value before being passed to the template. Correct? This is odd because array1 in the constructor should be passed by reference. If it get expanded to a literal, in the context of a mixin template, it no longer refers to the same data. I wonder if this is a bug in the implementation of mixin templates. Again, this assumes that .stringof reflects what code is being generated by the template. Any idea?
May 25 2016