digitalmars.D - PackedAliasSeq?
- Andrei Alexandrescu (32/32) Feb 22 2018 After coding https://github.com/dlang/phobos/pull/6192 with AliasSeq,
- Seb (4/10) Feb 22 2018 You could also extend the existing `Pack` template:
- deadalnix (3/39) Feb 23 2018 Isn't a packed AliasSeq just a tuple ?
- Petar Kirov [ZombineDev] (5/54) Feb 24 2018 It is not a tuple (in the `std.typecons.Tuple` sense) if it can
- John Colvin (37/73) Feb 24 2018 Yes, I love this stuff, lots of possibilities.
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (27/31) Feb 26 2018 I started playing around with this a few days ago, and came up
After coding https://github.com/dlang/phobos/pull/6192 with AliasSeq, the experience has been quite pleasurable. However, in places the AliasSeq tends to expand too eagerly, leading to a need to "keep it together" e.g. when you need to pass two of those to a template. I worked around the issue by nesting templates like this: template Merge(T...) { template With(U...) { static if (T.length == 0) alias With = U; else static if (U.length == 0) alias With = T; else static if (T[0] < U[0] || T[0] == U[0] && T[1].stringof <= U[1].stringof) alias With = AliasSeq!(T[0], T[1], Merge!(T[2 .. $]).With!U); else alias With = AliasSeq!(U[0], U[1], Merge!T.With!(U[2 .. $])); } } So instead of the unworkable Merge!(AliasSeq!(...), AliasSeq!(...)), one would write Merge!(AliasSeq!(...)).With!(AliasSeq!(...)). The problem remains for other use cases, so I was thinking of adding to std.meta this simple artifact: template PackedAliasSeq!(T...) { alias expand = AliasSeq!T; } That way, everything stays together and can be expanded on demand. Andrei
Feb 22 2018
On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei Alexandrescu wrote:After coding https://github.com/dlang/phobos/pull/6192 with AliasSeq, the experience has been quite pleasurable. However, in places the AliasSeq tends to expand too eagerly, leading to a need to "keep it together" e.g. when you need to pass two of those to a template. [...]You could also extend the existing `Pack` template: https://github.com/dlang/phobos/blob/master/std/meta.d#L1704
Feb 22 2018
On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei Alexandrescu wrote:After coding https://github.com/dlang/phobos/pull/6192 with AliasSeq, the experience has been quite pleasurable. However, in places the AliasSeq tends to expand too eagerly, leading to a need to "keep it together" e.g. when you need to pass two of those to a template. I worked around the issue by nesting templates like this: template Merge(T...) { template With(U...) { static if (T.length == 0) alias With = U; else static if (U.length == 0) alias With = T; else static if (T[0] < U[0] || T[0] == U[0] && T[1].stringof <= U[1].stringof) alias With = AliasSeq!(T[0], T[1], Merge!(T[2 .. $]).With!U); else alias With = AliasSeq!(U[0], U[1], Merge!T.With!(U[2 .. $])); } } So instead of the unworkable Merge!(AliasSeq!(...), AliasSeq!(...)), one would write Merge!(AliasSeq!(...)).With!(AliasSeq!(...)). The problem remains for other use cases, so I was thinking of adding to std.meta this simple artifact: template PackedAliasSeq!(T...) { alias expand = AliasSeq!T; } That way, everything stays together and can be expanded on demand. AndreiIsn't a packed AliasSeq just a tuple ?
Feb 23 2018
On Saturday, 24 February 2018 at 06:14:52 UTC, deadalnix wrote:On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei Alexandrescu wrote:It is not a tuple (in the `std.typecons.Tuple` sense) if it can contain values, types and other kinds of symbols. I think a more appropriate name would be AliasTuple - an AliasSeq that doesn't auto-expand.After coding https://github.com/dlang/phobos/pull/6192 with AliasSeq, the experience has been quite pleasurable. However, in places the AliasSeq tends to expand too eagerly, leading to a need to "keep it together" e.g. when you need to pass two of those to a template. I worked around the issue by nesting templates like this: template Merge(T...) { template With(U...) { static if (T.length == 0) alias With = U; else static if (U.length == 0) alias With = T; else static if (T[0] < U[0] || T[0] == U[0] && T[1].stringof <= U[1].stringof) alias With = AliasSeq!(T[0], T[1], Merge!(T[2 .. $]).With!U); else alias With = AliasSeq!(U[0], U[1], Merge!T.With!(U[2 .. $])); } } So instead of the unworkable Merge!(AliasSeq!(...), AliasSeq!(...)), one would write Merge!(AliasSeq!(...)).With!(AliasSeq!(...)). The problem remains for other use cases, so I was thinking of adding to std.meta this simple artifact: template PackedAliasSeq!(T...) { alias expand = AliasSeq!T; } That way, everything stays together and can be expanded on demand. AndreiIsn't a packed AliasSeq just a tuple ?
Feb 24 2018
On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei Alexandrescu wrote:After coding https://github.com/dlang/phobos/pull/6192 with AliasSeq, the experience has been quite pleasurable. However, in places the AliasSeq tends to expand too eagerly, leading to a need to "keep it together" e.g. when you need to pass two of those to a template. I worked around the issue by nesting templates like this: template Merge(T...) { template With(U...) { static if (T.length == 0) alias With = U; else static if (U.length == 0) alias With = T; else static if (T[0] < U[0] || T[0] == U[0] && T[1].stringof <= U[1].stringof) alias With = AliasSeq!(T[0], T[1], Merge!(T[2 .. $]).With!U); else alias With = AliasSeq!(U[0], U[1], Merge!T.With!(U[2 .. $])); } } So instead of the unworkable Merge!(AliasSeq!(...), AliasSeq!(...)), one would write Merge!(AliasSeq!(...)).With!(AliasSeq!(...)). The problem remains for other use cases, so I was thinking of adding to std.meta this simple artifact: template PackedAliasSeq!(T...) { alias expand = AliasSeq!T; } That way, everything stays together and can be expanded on demand. AndreiYes, I love this stuff, lots of possibilities. E.g. import std.traits : isInstanceOf; import std.meta : allSatisfy, AliasSeq, staticMap, Alias; template Pack(T ...) { alias expand = T; enum length = expand.length; } enum isPack(alias T) = isInstanceOf!(Pack, T); template Head(alias P) if (isPack!P) { alias Head = Alias!(P.expand[0]); } template Tail(alias P) if (isPack!P) { alias Tail = Pack!(P.expand[1 .. $]); } template staticZip(Seqs ...) if (Seqs.length >= 2 && allSatisfy!(isPack, Seqs)) { enum len = Seqs[0].length; static foreach (Seq; Seqs[1 .. $]) static assert(Seq.length == len, "All arguments to staticZip must have the same length"); static if (len == 0) alias staticZip = AliasSeq!(); else alias staticZip = AliasSeq!(Pack!(staticMap!(Head, Seqs)), staticZip!(staticMap!(Tail, Seqs))); }
Feb 24 2018
On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei Alexandrescu wrote:template PackedAliasSeq!(T...) { alias expand = AliasSeq!T; }I started playing around with this a few days ago, and came up with another interesting abstraction - NamedPack: alias foo = NamedPack!("Type", int, "name", "foo"); assert(is(foo.Type == int)); assert(foo.name == "foo"); assert(foo.equals!(NamedPack!("Type", int, "name", "foo"))); And for good measure, a helper to define your own 'compile-time structs', for want of a better word: alias Field = DefinePack!("Type", Type, "name", string, "offset", int); alias field1 = Field!(int, "a", 0); assert(is(field1.Type == int)); assert(field1.name == "a"); assert(field1.offset == 0); assert(field1.equals!(NamedPack!("Type", int, "name", "a", "offset", 0))); One benefit over regular structs being of course that these will never end up in the binary. The more structured nature of this construct over the simple Pack template makes it useful where information would otherwise be Implementation and some more documentation: https://gist.github.com/Biotronic/8a2664c050f01aed5e0c45950509022b -- Simen
Feb 26 2018