Mixin programming foreach

Tejas notrealemail at gmail.com
Mon Sep 27 17:20:33 UTC 2021


On Monday, 27 September 2021 at 16:23:50 UTC, eXodiquas wrote:
> Howdy ho everyone,
>
> I found this forum very helpful for my (maybe) stupid 
> questions, so I give it a try again because I don't understand 
> what's happening here.
>
> First of all, I'm not exactly sure what this code here, from 
> the documentation at https://dlang.org/articles/mixin.html, 
> does:
>
> ```d
> template GenStruct(string Name, string M1)
> {
>     const char[] GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ 
> "; }";
> }
>
> mixin(GenStruct!("Foo", "bar"));
> ```
>
> In my understanding we create a template called `GenStruct` 
> with compile time arguments `Name` and `M1`. We then create the 
> `char[] GenStruct` which holds the source code for the 
> `struct`. Afterwards we do the `mixin`call and create the 
> source code during compile time to have it ready to go. But I 
> don't understand why the `char[] GenStruct` is there. Is this 
> the name of the `mixin` or is the `template GenStruct` the name 
> of what we pass to the `mixin`? Can we create more than one 
> const char[] in one `template` scope and what would it do if we 
> could? So I'm a bit confused here.
>
> But nevertheless, I copied the code and changed it a bit to 
> something like this:
>
> ```d
> template Vector(int dimension) {
>   string cps = "";
>   foreach(d; 0..dimension) {
>     cps ~= "x" ~ d ~ " = 0;\n";
>   }
>   const char[] Vector = "struct Vector {\n" ~ 
> dimension.to!string ~ cps ~ "}";
> }
> ```
> In my head a call to `mixin(Vector!5)` should result in 
> something like this:
>
> ```d
> struct Vector5 {
>   int x0;
>   int x1;
>   int x2;
>   int x3;
>   int x4;
> }
> ```
> But it does not compile because `Error: declaration expected, 
> not foreach` which I understand as "foreach is not possible 
> during compile time", whereas I don't see any problem with 
> compile time availability of anything in this template. 
> Obviously I don't understand something here, so it would be 
> awesome if someone could help me out here. :P
>
> And as a final question. Let's say the above problems are all 
> solved and I construct such a template. How could I build 
> functions that take any of those `Vector`s as an argument?
> For example I want to add two of those, the function would look 
> something like this, or am I lost again?
>
> ```d
> Vector!T add(Vector!T lhs, Vector!T rhs) {
>   return ?;
> }
> ```
> How could I iterate over all components if such a `Vector`?
>
> I hope I am not on the completely wrong track to tackle this 
> problem.
>
> Thanks in advance. :)
>
> eXodiquas

You are trying to write arbitrary statements inside a template, 
that will not work(if you insist on writing code that way, use 
[string mixins](http://ddili.org/ders/d.en/mixin.html)(please 
don't use them unless absolutely necessary)

Now, to solve your problem:
```d
struct Vector(int T){
     int[T] elems;
}
```

And that's it :D

Now, how to use it?

Here is an isolated code fragment:
```d
auto Add(T: Vector!U,int U)(T a, T b){ /*Yes, you don't have to 
write different funcs for different instantiations of Vector :D*/
     int[] c;
     c.length = U;

     for(size_t i = 0; i < U; i++){
         c[i] = a.elems[i] + b.elems[i];
     }
     return Vector!U(c);
}
```

Full code:

```d
import std;

struct Vector(int t){
     int[t] elems;
     size_t length = t;


     this(int[] input){
         assert(input.length <= length);
         foreach(i,num; input){
             elems[i] = num;
         }
     }

     this(int num){
         elems = num;
     }

     void displayElems(){
     	import std.stdio;
     	foreach(elem; elems){
         	writeln(elem);
     	}
     }

}

auto Add(T: Vector!U,int U)(T a, T b){
     int[] c;
     c.length = U;

     for(size_t i = 0; i < U; i++){
         c[i] = a.elems[i] + b.elems[i];
     }
     return Vector!U(c);
}

void main(){
     auto first = Vector!10([7,896,864, 8976]);
     auto second = Vector!10([23,7890,9886]);
     auto third = Vector!10(5);
     auto result = Add(first, second);
     writeln(result);
     result.displayElems;
     third.displayElems;
}
```


More information about the Digitalmars-d-learn mailing list