www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Concatenating compile time sequences

reply Victor Porton <porton narod.ru> writes:
I try to split a compile time sequence of types and names into a 
sequence consisting of two-element subsequences (each of type and 
name).

That is, I want to transform:

(int, "x", float, "y", double, "z")

into

(AliasSeq!(int, "x"), AliasSeq!(float, "y"), AliasSeq!(double, 
"z"))

I am trying like this:

private alias enum processFields() = AliasSeq!();

private alias enum processFields(T, name, Fields...) =
     AliasSeq!(AliasSeq!(T, name), processFields!(Fields));

But the above would (as I understand) make AliasSeq! returned by 
the recursively called processFields an element of the parent 
sequence rather than its tail subsequence as it should.

Please help to fix the above code. I want namely a recursive 
implementation like the above, because I am going to generalize 
it for some more complex cases.
Mar 01
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Mar 02, 2019 at 02:16:22AM +0000, Victor Porton via Digitalmars-d-learn
wrote:
 I try to split a compile time sequence of types and names into a
 sequence consisting of two-element subsequences (each of type and
 name).
 
 That is, I want to transform:
 
 (int, "x", float, "y", double, "z")
 
 into
 
 (AliasSeq!(int, "x"), AliasSeq!(float, "y"), AliasSeq!(double, "z"))
Keep in mind that sequences produced by AliasSeq are auto-expanding, meaning the above construct will automatically flatten into a flat AliasSeq!(int, "x", float, "y", double, "z"). If that's not what you want, you need to wrap your subsequences in a separate, non-eponymous template.
 I am trying like this:
 
 private alias enum processFields() = AliasSeq!();
I'm not sure what "alias enum" is supposed to mean; is that a typo? Surely you mean just "alias"?
 private alias enum processFields(T, name, Fields...) =
     AliasSeq!(AliasSeq!(T, name), processFields!(Fields));
This line doesn't do what you think it does, because of auto-expansion. It's essentially exactly the same thing as: private alias processFields(T, name, Fields...) = AliasSeq!(T, name, processFields!(Fields)); i.e., the nested AliasSeq has no effect.
 But the above would (as I understand) make AliasSeq! returned by the
 recursively called processFields an element of the parent sequence
 rather than its tail subsequence as it should.
If you want anything that retains a nested structure, you cannot use AliasSeq because of auto-expansion. You need to define your own, non-eponymous template container, e.g.: template MySeq(T...) { alias data = T; } alias processFields(T, name, Fields...) = AliasSeq!(MySeq!(T, name), MySeq!(processFields!(Fields))); The MySeq!(...) "protect" their contents from flattening into the outer list, while the outer AliasSeq causes individual MySeq!(...)'s to be promoted to the top level sequence rather than producing a tree-like structure. Note that to access the data inside a MySeq, you'll have to use .data, for example: alias fields = processFields!(int, "x", float, "y"); alias type0 = fields[0].data[0]; // int string name0 = fields[0].data[1]; // "x" alias type1 = fields[1].data[0]; // float string name1 = fields[1].data[1]; // "y" Hope this helps. T -- Windows: the ultimate triumph of marketing over technology. -- Adrian von Bidder
Mar 01
parent aliak <something something.com> writes:
On Saturday, 2 March 2019 at 02:38:09 UTC, H. S. Teoh wrote:
 On Sat, Mar 02, 2019 at 02:16:22AM +0000, Victor Porton via 
 Digitalmars-d-learn wrote:
 [...]
Keep in mind that sequences produced by AliasSeq are auto-expanding, meaning the above construct will automatically flatten into a flat AliasSeq!(int, "x", float, "y", double, "z"). If that's not what you want, you need to wrap your subsequences in a separate, non-eponymous template.
 [...]
I'm not sure what "alias enum" is supposed to mean; is that a typo? Surely you mean just "alias"?
     [...]
This line doesn't do what you think it does, because of auto-expansion. It's essentially exactly the same thing as: private alias processFields(T, name, Fields...) = AliasSeq!(T, name, processFields!(Fields)); i.e., the nested AliasSeq has no effect.
 [...]
If you want anything that retains a nested structure, you cannot use AliasSeq because of auto-expansion. You need to define your own, non-eponymous template container, e.g.: template MySeq(T...) { alias data = T; } alias processFields(T, name, Fields...) = AliasSeq!(MySeq!(T, name), MySeq!(processFields!(Fields))); The MySeq!(...) "protect" their contents from flattening into the outer list, while the outer AliasSeq causes individual MySeq!(...)'s to be promoted to the top level sequence rather than producing a tree-like structure. Note that to access the data inside a MySeq, you'll have to use .data, for example: alias fields = processFields!(int, "x", float, "y"); alias type0 = fields[0].data[0]; // int string name0 = fields[0].data[1]; // "x" alias type1 = fields[1].data[0]; // float string name1 = fields[1].data[1]; // "y" Hope this helps. T
There's a package called bolts that has an AliasPack defined that could allow you to do something like: template split(seq...) if (seq.length % 2 == 0) { static if (seq.length >= 2) { alias Pair = AliasPack!(seq[0], seq[1]); alias split = AliasSeq!(Pair, .split!(seq[2..$])); } else { alias split = AliasSeq!(); } } Running code: https://run.dlang.io/is/lfTOBz Cheers, - Ali
Mar 03