www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Sequence separation

reply Engine Machine <EM EM.com> writes:
alias x = AliasSeq!(a, b, AliasSeq!(c, d));

results in a flat sequence. I would like to be able to keep them 
separate so I can have sub sequences.

x.length == 4;
Aug 16 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 16 August 2016 at 19:17:27 UTC, Engine Machine wrote:
 alias x = AliasSeq!(a, b, AliasSeq!(c, d));

 results in a flat sequence. I would like to be able to keep 
 them separate so I can have sub sequences.
wrap them in a struct.
Aug 16 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe wrote:
 On Tuesday, 16 August 2016 at 19:17:27 UTC, Engine Machine 
 wrote:
 alias x = AliasSeq!(a, b, AliasSeq!(c, d));

 results in a flat sequence. I would like to be able to keep 
 them separate so I can have sub sequences.
wrap them in a struct.
You mean something like: struct MySequence(Args...) { enum length = Args.length; alias args = Args; } alias x = MySequence!(a, b, MySequence!(c, d)); static assert(x.length == 3) static assert(x.args[2].length == 2);
Aug 17 2016
parent reply Engine Machine <EM EM.com> writes:
On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta 
wrote:
 On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe wrote:
 On Tuesday, 16 August 2016 at 19:17:27 UTC, Engine Machine 
 wrote:
 alias x = AliasSeq!(a, b, AliasSeq!(c, d));

 results in a flat sequence. I would like to be able to keep 
 them separate so I can have sub sequences.
wrap them in a struct.
You mean something like: struct MySequence(Args...) { enum length = Args.length; alias args = Args; } alias x = MySequence!(a, b, MySequence!(c, d)); static assert(x.length == 3) static assert(x.args[2].length == 2);
Thanks, basically works. How can I test, though, if a argument uses a MySequence? I can't do if (Args[0] == MySequence) because MySequence is templated. While I could test for a length, that doesn't work because some types have a length. I could add another enum to MySequence, but again, not safe. I could do some string tests, but that doesn't work. in your exmaple, if (x.args[2] == MySequence) ?? I simply need to differentiate between a parameter/arg being a MySequence and not.
Aug 17 2016
next sibling parent reply ag0aep6g <anonymous example.com> writes:
On 08/17/2016 08:38 PM, Engine Machine wrote:
 On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta wrote:
[...]
 You mean something like:

 struct MySequence(Args...)
 {
     enum length = Args.length;
     alias args = Args;
 }

 alias x = MySequence!(a, b, MySequence!(c, d));

 static assert(x.length == 3)
 static assert(x.args[2].length == 2);
Thanks, basically works. How can I test, though, if a argument uses a MySequence? I can't do if (Args[0] == MySequence) because MySequence is templated. While I could test for a length, that doesn't work because some types have a length. I could add another enum to MySequence, but again, not safe. I could do some string tests, but that doesn't work. in your exmaple, if (x.args[2] == MySequence) ?? I simply need to differentiate between a parameter/arg being a MySequence and not.
With MySequence being a type, you can do this: ---- static if (is(x.args[2] == MySequence!Args, Args ...)) { ... } ---- Aside from this check, there is probably not much use for MySequence being a type. So I'm be tempted to find a way to do the check with a raw template MySequence. As you said, another enum alone doesn't cut it. The faker can just add the same enum. But a private enum of a private type might do it: ---- template MySequence(Args ...) { /* ... length and args ... */ private enum id = Id(); } private struct Id {} enum isMySequence(alias seq) = is(typeof(seq.id) == Id); ---- Other modules can't use the Id type directly, because it's private. And they can't use typeof(MySequence!foo.id), because the id member is private, too. However, I wouldn't be surprised if this can be circumvented too.
Aug 17 2016
next sibling parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote:
 On 08/17/2016 08:38 PM, Engine Machine wrote:
 On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico 
 Giaretta wrote:
[...]
 You mean something like:

 struct MySequence(Args...)
 {
     enum length = Args.length;
     alias args = Args;
 }

 alias x = MySequence!(a, b, MySequence!(c, d));

 static assert(x.length == 3)
 static assert(x.args[2].length == 2);
Thanks, basically works. How can I test, though, if a argument uses a MySequence? I can't do if (Args[0] == MySequence) because MySequence is templated. While I could test for a length, that doesn't work because some types have a length. I could add another enum to MySequence, but again, not safe. I could do some string tests, but that doesn't work. in your exmaple, if (x.args[2] == MySequence) ?? I simply need to differentiate between a parameter/arg being a MySequence and not.
With MySequence being a type, you can do this: ---- static if (is(x.args[2] == MySequence!Args, Args ...)) { ... } ---- Aside from this check, there is probably not much use for MySequence being a type. So I'm be tempted to find a way to do the check with a raw template MySequence.
import std.traits: TemplateOf; static if (__traits(isSame, TemplateOf!(x.args[2]), MySequence)) { ... } std.traits.TemplateOf extracts the symbol representing the uninstantiated template. __traits(isSame, symbol1, symbol2) evaluates at compile time to true if and only if the two symbols represent the same thing (be it a type, an uninstantiated template, an instantiated one or whatever else).
Aug 17 2016
next sibling parent Engine Machine <EM EM.com> writes:
On Wednesday, 17 August 2016 at 19:21:57 UTC, Lodovico Giaretta 
wrote:
 On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote:
 [...]
import std.traits: TemplateOf; static if (__traits(isSame, TemplateOf!(x.args[2]), MySequence)) { ... } std.traits.TemplateOf extracts the symbol representing the uninstantiated template. __traits(isSame, symbol1, symbol2) evaluates at compile time to true if and only if the two symbols represent the same thing (be it a type, an uninstantiated template, an instantiated one or whatever else).
Thanks! To note, it error's if there is no match ;/
Aug 17 2016
prev sibling parent ag0aep6g <anonymous example.com> writes:
On 08/17/2016 09:21 PM, Lodovico Giaretta wrote:
 import std.traits: TemplateOf;
 static if (__traits(isSame, TemplateOf!(x.args[2]), MySequence))
 {
     ...
 }

 std.traits.TemplateOf extracts the symbol representing the
 uninstantiated template.

 __traits(isSame, symbol1, symbol2) evaluates at compile time to true if
 and only if the two symbols represent the same thing (be it a type, an
 uninstantiated template, an instantiated one or whatever else).
Look at that! Much better. TemplateOf is implemented with a template specialization, which can handle other things than types, unlike `is(...)`. Using that directly, without going to std.traits, isMySequence could be done like this: ---- enum isMySequence(alias thing : MySequence!args, args ...) = true; enum isMySequence(alias thing) = false; ---- That's just me toying around with the language, of course. The isSame+TemplateOf version is perfectly fine.
Aug 17 2016
prev sibling parent reply Engine Machine <EM EM.com> writes:
On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote:
 On 08/17/2016 08:38 PM, Engine Machine wrote:
 [...]
[...]
 [...]
With MySequence being a type, you can do this: ---- static if (is(x.args[2] == MySequence!Args, Args ...)) { ... } ----
It works! Nifty that you can do that with is.
 Aside from this check, there is probably not much use for 
 MySequence being a type. So I'm be tempted to find a way to do 
 the check with a raw template MySequence.

 As you said, another enum alone doesn't cut it. The faker can 
 just add the same enum.

 But a private enum of a private type might do it:

 ----
 template MySequence(Args ...)
 {
     /* ... length and args ... */
     private enum id = Id();
 }

 private struct Id {}

 enum isMySequence(alias seq) =  is(typeof(seq.id) == Id);
 ----

 Other modules can't use the Id type directly, because it's 
 private. And they can't use typeof(MySequence!foo.id), because 
 the id member is private, too.

 However, I wouldn't be surprised if this can be circumvented 
 too.
Well, the is does work and that probably is the best solution. I don't mind the extra type at this point. Of course, a library solution for this type of stuff would be nice. I'd rather not have to even use a type but rather use arrays: [a,b,[c,d]].
Aug 17 2016
parent Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Wednesday, 17 August 2016 at 19:38:22 UTC, Engine Machine 
wrote:
 Well, the is does work and that probably is the best solution. 
 I don't mind the extra type at this point. Of course, a library 
 solution for this type of stuff would be nice. I'd rather not 
 have to even use a type but rather use arrays:
 [a,b,[c,d]].
Maybe you can use Tuple from std.typecons, instead of custom structs, that group the arguments. Ex: alias seqWithSubSeq = AliasSeq!(a, b, Tuple!(c, d))
Aug 21 2016
prev sibling parent Engine Machine <EM EM.com> writes:
On Wednesday, 17 August 2016 at 18:38:48 UTC, Engine Machine 
wrote:
 On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta 
 wrote:
 On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe 
 wrote:
 [...]
You mean something like: struct MySequence(Args...) { enum length = Args.length; alias args = Args; } alias x = MySequence!(a, b, MySequence!(c, d)); static assert(x.length == 3) static assert(x.args[2].length == 2);
Thanks, basically works. How can I test, though, if a argument uses a MySequence? I can't do if (Args[0] == MySequence) because MySequence is templated. While I could test for a length, that doesn't work because some types have a length. I could add another enum to MySequence, but again, not safe. I could do some string tests, but that doesn't work. in your exmaple, if (x.args[2] == MySequence) ?? I simply need to differentiate between a parameter/arg being a MySequence and not.
I guess I'll go with something like static if ((a.Args[2]).stringof[0..11] == "MySequence!") Doesn't feel entirely safe but probably will work without issue. Maybe there is a better way?
Aug 17 2016