Thread overview
String mixin from within a template
Aug 23, 2020
data pulverizer
Aug 23, 2020
ag0aep6g
Aug 23, 2020
data pulverizer
Aug 23, 2020
ag0aep6g
Aug 23, 2020
data pulverizer
August 23, 2020
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.

August 23, 2020
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)
August 23, 2020
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

August 23, 2020
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".
August 23, 2020
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!