www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Create template expression sequence

reply Menshikov <mensikovk817 gmail.com> writes:
```d
import std.meta, std.stdio;

auto get0(A...)() => A[0];

struct A{int a = 4; int b = 2;}

void main(){
    AliasSeq!(4, 2)[0].writeln;
    get0!(4, 2).writeln;
    A a;
    a.tupleof[0].writeln;
    get0!(a.tupleof).writeln;//error :(
}
```
I think this is a very, very big problem. Because of this 
problem, there is literally a hell of string mixins going on. For 
example, I have a structure A, it has some methods that I mark 
with the Attr attribute. The task is to write a function that 
will call each method of the argument a with such an attribute 
and write its all attributes.

```d
enum Attr;

struct A{
	int sample(float a) => cast(int) a + 1;//nope
      Attr int sample(int a) => a;//yep
}


void func(A)(in A a, int arg){
     static foreach(symbol; getSymbolsByUDA!(A, Attr)){
         /* and so, I need to call the `symbol` method via a.
         This is where the problems begin,
         because if I just can't do this mixin ("a." ~ 
Field.stringof)
         I lose which overload I need to use */
     }
}
```

Something terrible is usually written here.

OR the information about the field/method will be divided 
literally into a separate variable that stores the value, and 
into alias, which stores only information for introspection.

OR declare `enum` (already a problem specifically for static 
foreach, if you want to declare something else outside the 
scope), which contains` "a." ~ Symbol.stringof`, and each time 
the variable is accessed, it is enclosed in mixin().

You also take into account that overloads are important here, 
which will increase unreadability.
It is not normal.

Even so, if I replace A with a class that inherits from another 
class that has  Attr, then getSymbolsByUDA literally breaks.

```d
enum Attr;

class B{
	 Attr int a;
}

class A: B{
	 Attr int b;
}

void main(){
	pragma(msg, getSymbolsByUDA!(A, Attr));//ERROR!
}
```

If we could pass through the template parameter AND information 
for introspection AND reference to runtime data, then there would 
be no such hell.

If it were ExprSeq for example, then it would be solved simply:
```d
void func(A)(in A a, int arg){
     static foreach(expr; getByUDA!(A, Attr)){
         expr(arg).writeln;//expr.stringof == q{a.sample};
         write("all UDAs: ");
         static foreach(uda; __traits(getAttributes, expr)){
         	uda.stringof.write();
         }
         writeln();
     }
}
```

I came across this when I was trying to bind D data to a script 
language.
Dec 02 2021
parent Paul Backus <snarwin gmail.com> writes:
On Thursday, 2 December 2021 at 15:54:17 UTC, Menshikov wrote:
 ```d
 import std.meta, std.stdio;

 auto get0(A...)() => A[0];

 struct A{int a = 4; int b = 2;}

 void main(){
    AliasSeq!(4, 2)[0].writeln;
    get0!(4, 2).writeln;
    A a;
    a.tupleof[0].writeln;
    get0!(a.tupleof).writeln;//error :(
 }
 ```
Easiest fix is to change `get0` to take its arguments as runtime parameters rather than template parameters: ```d auto get0(Args...)(auto ref Args args) => args[0]; ``` Full example: https://run.dlang.io/is/5LVeyY
 ```d
 enum Attr;

 struct A{
 	int sample(float a) => cast(int) a + 1;//nope
      Attr int sample(int a) => a;//yep
 }


 void func(A)(in A a, int arg){
     static foreach(symbol; getSymbolsByUDA!(A, Attr)){
         /* and so, I need to call the `symbol` method via a.
         This is where the problems begin,
         because if I just can't do this mixin ("a." ~ 
 Field.stringof)
         I lose which overload I need to use */
     }
 }
 ```
You can use [`__traits(child)`][1] to bind a member symbol to an object: ```d void func(A)(A a, int arg){ import std.traits, std.stdio; static foreach(symbol; getSymbolsByUDA!(A, Attr)){ writeln(__traits(child, a, symbol)(arg)); } } ``` Full example: https://run.dlang.io/is/Dg6INi [1]: https://dlang.org/spec/traits.html#child
 ```d
 enum Attr;

 class B{
 	 Attr int a;
 }

 class A: B{
 	 Attr int b;
 }

 void main(){
 	pragma(msg, getSymbolsByUDA!(A, Attr));//ERROR!
 }
 ```
Bug report: https://issues.dlang.org/show_bug.cgi?id=17870 Looks like there was an attempt to fix it that got abandoned close to the finish line: https://github.com/dlang/dmd/pull/11633
Dec 02 2021