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