www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - String mixin from within a template

reply data pulverizer <data.pulverizer gmail.com> writes:
Hi all,

I am trying to dynamically create compile time variables by using 
string and template mixins. I have tried both approaches and they 
have failed. The central thing I am trying to create is a line 
like this:

```d
`alias x` ~ i ~ ` = Remove(indexes[i] - i, Args);`
```

where a compile time variable xi that is x0, x1, ... is created 
and this:

```d
`alias x` ~ i ~ ` = Remove(indexes[i] - i, x`~ (i - 1) ~ `);`
```

a similar idea but on the other side we have x(i-1) so for i = 1:

```d
alias x1 = Remove(indices[i] - i, x0);
```

Here is the template mixin approach for the first:

```d
mixin template MakeString1(alias i)
{
   mixin(`alias x` ~ i ~ ` = Remove(indices[i] - i, Args);`);
}
```

and the string mixin for the second approach:

```d
template Remove(long[] indices, Args...)
{
   enum N = indices.length;
   static foreach(i; 0..N)
   {
     static if(i == 0)
     {
       //template mixin approach
       mixin MakeString1!(i);
     }else{
       // string mixin apprach
       enum _string_ = `alias x` ~ i ~ ` = Remove(indices[i] - i, 
x`~ (i - 1) ~ `);`;
       mixin(_string_);
     }
   }
   mixin(`alias Remove = x` ~ i ~ `;`);
}
```

The `Remove` in the template body is an overload and works fine, 
but my attempt to use these approaches to dynamically overload 
has failed. I get errors like

```d
Error: no identifier for declarator x
```

Indicating that the concatenation `~` is not working, and I only 
get the partial string when I print out `pragma(msg, _string_);`


Thanks in advance for your help.
Aug 23 2020
parent reply ag0aep6g <anonymous example.com> writes:
On Sunday, 23 August 2020 at 19:42:47 UTC, data pulverizer wrote:
 `alias x` ~ i ~ ` = Remove(indexes[i] - i, x`~ (i - 1) ~ `);`
[...]
 ```d
 Error: no identifier for declarator x
 ```

 Indicating that the concatenation `~` is not working, and I 
 only get the partial string when I print out `pragma(msg, 
 _string_);`
You're having a misconception about concatenation. This: "foo " ~ 65 ~ " bar" does not produce the string "foo 65 bar". It produces the string "foo A bar", because 65 == 'A'. In your case, when i == 0, you get a null byte in the string, which is probably the cause for the partial output. You can use std.conv or std.format to make a string from a number: text("foo ", 65, " bar") format("foo %s bar", 65)
Aug 23 2020
parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Sunday, 23 August 2020 at 20:12:12 UTC, ag0aep6g wrote:
 On Sunday, 23 August 2020 at 19:42:47 UTC, data pulverizer 
 wrote:
 `alias x` ~ i ~ ` = Remove(indexes[i] - i, x`~ (i - 1) ~ `);`
[...]
 ```d
 Error: no identifier for declarator x
 ```

 Indicating that the concatenation `~` is not working, and I 
 only get the partial string when I print out `pragma(msg, 
 _string_);`
You're having a misconception about concatenation. This: "foo " ~ 65 ~ " bar" does not produce the string "foo 65 bar". It produces the string "foo A bar", because 65 == 'A'. In your case, when i == 0, you get a null byte in the string, which is probably the cause for the partial output. You can use std.conv or std.format to make a string from a number: text("foo ", 65, " bar") format("foo %s bar", 65)
Thanks for your update. I have changed the code: ```d import std.conv: text; template Remove(alias indices, Args...) { enum N = indices.length; static foreach(i; 0..N) { static if(i == 0) { enum _string0_ = text(`alias x`, i, ` = Remove(indicies[i] - i, Args);`); pragma(msg, "compiled string 1: ", _string0_); mixin(_string0_); }else{ enum _string1_ = text(`alias x`, i, ` = Remove(indicies[i] - i, x`, (i - 1), `);`); pragma(msg, "compiled string 2: ", _string1_); mixin(_string1_); } } enum _string2_ = text(`alias Remove = x`, N - 1, `;`); pragma(msg, "compiled string 3: ", _string2_); mixin(_string2_); } ``` and I am getting the following errors: ``` compiled string 1: alias x0 = Remove(indicies[i] - i, Args); Error: found - when expecting ) Error: semicolon expected to close alias declaration Error: no identifier for declarator i Error: declaration expected, not , ... repeated for the other two cases ... ``` Thanks
Aug 23 2020
parent reply ag0aep6g <anonymous example.com> writes:
On Sunday, 23 August 2020 at 20:54:22 UTC, data pulverizer wrote:
 compiled string 1: alias x0 = Remove(indicies[i] - i, Args);
 Error: found - when expecting )
 Error: semicolon expected to close alias declaration
 Error: no identifier for declarator i
 Error: declaration expected, not ,
 ... repeated for the other two cases ...
As the compiler tells you, the line alias x0 = Remove(indicies[i] - i, Args); doesn't parse. You can't assign the result of a function call to an `alias`. If `Remove` is indeed a function, you need to use `enum` instead of `alias`. If `Remove` is a template, you're missing an exclamation mark. You also have a typo: "indicies" should be "indices".
Aug 23 2020
parent data pulverizer <data.pulverizer gmail.com> writes:
On Sunday, 23 August 2020 at 21:13:51 UTC, ag0aep6g wrote:
 On Sunday, 23 August 2020 at 20:54:22 UTC, data pulverizer 
 wrote:
 compiled string 1: alias x0 = Remove(indicies[i] - i, Args);
 Error: found - when expecting )
 Error: semicolon expected to close alias declaration
 Error: no identifier for declarator i
 Error: declaration expected, not ,
 ... repeated for the other two cases ...
As the compiler tells you, the line alias x0 = Remove(indicies[i] - i, Args); doesn't parse. You can't assign the result of a function call to an `alias`. If `Remove` is indeed a function, you need to use `enum` instead of `alias`. If `Remove` is a template, you're missing an exclamation mark. You also have a typo: "indicies" should be "indices".
Good spot on both accounts, I've also made other changes and its finally working. Many thanks!
Aug 23 2020