digitalmars.D.learn - Making enum join variadic
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (40/40) May 01 2014 How can I make `join` variadic (by filling in njoin) in the
- bearophile (9/11) May 01 2014 When you have a D tuple (not Phobos tuple), and it contains
- Artur Skawina via Digitalmars-d-learn (20/21) May 01 2014 import std.array, std.range, std.algorithm;
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (36/37) May 02 2014 Thx!
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (1/1) May 02 2014 Its up: https://github.com/nordlow/justd/blob/master/enums.d
- Philippe Sigaud via Digitalmars-d-learn (10/15) May 02 2014 I'd be verbose. It's an uncommon operation, bound to surprise a reader
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (5/15) May 02 2014 This should give a better error message, than current mixin error.
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (25/44) May 02 2014 Here's my try at detecting member names collision at compile time:
- Meta (2/7) May 02 2014 Associative arrays are not CTFE-able.
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (3/11) May 02 2014 So that leaves me with using an array of bool and rank() then, I
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (1/3) May 02 2014 Correction: I mean array of strings and find.
- Artur Skawina via Digitalmars-d-learn (5/29) May 02 2014 Move the AA declaration to inside the lambda, remove the 'static'
- Meta (3/38) May 02 2014 But that will also move the compile time check to a runtime one.
- Artur Skawina via Digitalmars-d-learn (3/35) May 02 2014 No; mixin arguments are always evaluated at CT.
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (3/4) May 02 2014 Collision detection should now be complete.
How can I make `join` variadic (by filling in njoin) in the following code? import std.stdio: writeln; import std.traits; string enumsHelper(S...)(S s) { typeof(return) r; foreach (i, e; s) { if (i >= 1) r ~= ", "; r ~= e; } return r; } /** Join/Chain/Concatenate/Unite Enums $(D E1), $(D E2), ... into $(D E). See also: http://forum.dlang.org/thread/f9vc6p$1b7k$1 digitalmars.com */ template join(string E, E1, E2) { const join = ("enum " ~ E ~ " { " ~ enumsHelper(__traits(allMembers, E1)) ~ "," ~ enumsHelper(__traits(allMembers, E2)) ~ " }" ); } template njoin(string E, Ei...) { import std.algorithm: map; enum string njoin = "enum " ~ E ~ " { " ~ "" ~ " } "; } void main(string[] args) { enum E1 { A, B, C } enum E2 { E, F, G } mixin(join!("E12", E1, E2)); E12 e12; writeln(e12.min, ",", e12.max); }
May 01 2014
Nordlöw:How can I make `join` variadic (by filling in njoin) in the following code?When you have a D tuple (not Phobos tuple), and it contains values all of the same type, you can turn it into an array with just: [mytuple] Once you have an array of strings, you can use the normal phobos function to join the strings as you desire. Bye, bearophile
May 01 2014
On 05/02/14 00:24, "Nordlöw" via Digitalmars-d-learn wrote:How can I make `join` variadic (by filling in njoin) in the following code?import std.array, std.range, std.algorithm; import std.stdio; template Njoin(ES...) { mixin({ string r = "enum Njoin { "; foreach (E; ES) r ~= [__traits(allMembers, E), " "].join(","); return r ~ "}"; }()); } void main(string[] args) { enum E1 { A, B, C } enum E2 { E, F, G } alias E12 = Njoin!(E1, E2); E12 e12; writeln(e12.min, ",", e12.max); } artur
May 01 2014
arturThx! Here's my final version that compiles and run: import std.stdio: writeln; import traits_ex: isEnum; import std.typetuple: allSatisfy; /** Join/Chain/Concatenate/Unite Enums $(D E1), $(D E2), ... into $(D E). See also: http://forum.dlang.org/thread/f9vc6p$1b7k$1 digitalmars.com */ template join(ES...) if (allSatisfy!(isEnum, ES)) { mixin({ string r = "enum join { "; foreach (E; ES) { import std.range: join; r ~= [__traits(allMembers, E), " "].join(","); } return r ~ "}"; }()); } unittest { enum E1 { a, b, c } enum E2 { e, f, g } enum E3 { h, i, j} alias E1_ = join!(E1); alias E12 = join!(E1, E2); alias E123 = join!(E1, E2, E3); writeln(E123.min, ",", E123.max); } Some final questions: - Is join a good naming for this? Is chain better? - Is it better to be verbose with joinEnums? - What other useful enum algorithms are you missing? - Should this perhaps go into Phobos? If so in what module? std.algorithm, range, traits?
May 02 2014
Its up: https://github.com/nordlow/justd/blob/master/enums.d
May 02 2014
On Fri, May 2, 2014 at 12:59 PM, "Nordlöw" <digitalmars-d-learn puremagic.com> wrote:Some final questions: - Is join a good naming for this? Is chain better? - Is it better to be verbose with joinEnums?I'd be verbose. It's an uncommon operation, bound to surprise a reader a bit.It's better to type a few more letters. I did not try to compile it, but what happens if the enum elements have the same name ? The same min/max/values ? Like this: enum E1 { a, b, c } alias E111 = join!(E1, E1, E1);- What other useful enum algorithms are you missing? - Should this perhaps go into Phobos? If so in what module? std.algorithm, range, traits?I would put it in std.typecons, since it's a type constructor
May 02 2014
I'd be verbose. It's an uncommon operation, bound to surprise a reader a bit.It's better to type a few more letters.See update.I did not try to compile it, but what happens if the enum elements have the same name ? The same min/max/values ? Like this: enum E1 { a, b, c } alias E111 = join!(E1, E1, E1);This should give a better error message, than current mixin error. I'll work on that.I would put it in std.typecons, since it's a type constructorOk. Thx!
May 02 2014
On Friday, 2 May 2014 at 12:45:44 UTC, Nordlöw wrote:Here's my try at detecting member names collision at compile time: template MemberNamesUnion(E...) if (allSatisfy!(isEnum, E)) { bool[string] allMembers; // used to detect member collisions mixin({ string r = "enum MemberNamesUnion { "; foreach (T; E) { import std.range: join; foreach (member; __traits(allMembers, T)) { static assert (member in allMembers, "Member collision"); allMembers[member] = true; } r ~= [__traits(allMembers, T)].join(",") ~ ","; } return r ~ " }"; }()); } It fails as enums.d(25,46): Error: static variable allMembers cannot be read at compile time enums.d(25,21): while evaluating: static assert("a" in allMembers) Is there a solution to this problem?I'd be verbose. It's an uncommon operation, bound to surprise a reader a bit.It's better to type a few more letters.See update.I did not try to compile it, but what happens if the enum elements have the same name ? The same min/max/values ? Like this: enum E1 { a, b, c } alias E111 = join!(E1, E1, E1);This should give a better error message, than current mixin error. I'll work on that.I would put it in std.typecons, since it's a type constructorOk. Thx!
May 02 2014
On Friday, 2 May 2014 at 13:38:39 UTC, Nordlöw wrote:enums.d(25,46): Error: static variable allMembers cannot be read at compile time enums.d(25,21): while evaluating: static assert("a" in allMembers) Is there a solution to this problem?Associative arrays are not CTFE-able.
May 02 2014
On Friday, 2 May 2014 at 14:36:16 UTC, Meta wrote:On Friday, 2 May 2014 at 13:38:39 UTC, Nordlöw wrote:So that leaves me with using an array of bool and rank() then, I guess...enums.d(25,46): Error: static variable allMembers cannot be read at compile time enums.d(25,21): while evaluating: static assert("a" in allMembers) Is there a solution to this problem?Associative arrays are not CTFE-able.
May 02 2014
So that leaves me with using an array of bool and rank() then, I guess...Correction: I mean array of strings and find.
May 02 2014
On 05/02/14 15:38, "Nordlöw" via Digitalmars-d-learn wrote:template MemberNamesUnion(E...) if (allSatisfy!(isEnum, E)) { bool[string] allMembers; // used to detect member collisions mixin({ string r = "enum MemberNamesUnion { "; foreach (T; E) { import std.range: join; foreach (member; __traits(allMembers, T)) { static assert (member in allMembers, "Member collision"); allMembers[member] = true; } r ~= [__traits(allMembers, T)].join(",") ~ ","; } return r ~ " }"; }()); } It fails as enums.d(25,46): Error: static variable allMembers cannot be read at compile time enums.d(25,21): while evaluating: static assert("a" in allMembers) Is there a solution to this problem?Move the AA declaration to inside the lambda, remove the 'static' from the assert, and fix the condition ("member !in allMembers"), then it will work. artur
May 02 2014
On Friday, 2 May 2014 at 15:18:06 UTC, Artur Skawina via Digitalmars-d-learn wrote:On 05/02/14 15:38, "Nordlöw" via Digitalmars-d-learn wrote:But that will also move the compile time check to a runtime one.template MemberNamesUnion(E...) if (allSatisfy!(isEnum, E)) { bool[string] allMembers; // used to detect member collisions mixin({ string r = "enum MemberNamesUnion { "; foreach (T; E) { import std.range: join; foreach (member; __traits(allMembers, T)) { static assert (member in allMembers, "Member collision"); allMembers[member] = true; } r ~= [__traits(allMembers, T)].join(",") ~ ","; } return r ~ " }"; }()); } It fails as enums.d(25,46): Error: static variable allMembers cannot be read at compile time enums.d(25,21): while evaluating: static assert("a" in allMembers) Is there a solution to this problem?Move the AA declaration to inside the lambda, remove the 'static' from the assert, and fix the condition ("member !in allMembers"), then it will work. artur
May 02 2014
On 05/02/14 17:27, Meta via Digitalmars-d-learn wrote:On Friday, 2 May 2014 at 15:18:06 UTC, Artur Skawina via Digitalmars-d-learn wrote:No; mixin arguments are always evaluated at CT. arturOn 05/02/14 15:38, "Nordlöw" via Digitalmars-d-learn wrote:But that will also move the compile time check to a runtime one.template MemberNamesUnion(E...) if (allSatisfy!(isEnum, E)) { bool[string] allMembers; // used to detect member collisions mixin({ string r = "enum MemberNamesUnion { "; foreach (T; E) { import std.range: join; foreach (member; __traits(allMembers, T)) { static assert (member in allMembers, "Member collision"); allMembers[member] = true; } r ~= [__traits(allMembers, T)].join(",") ~ ","; } return r ~ " }"; }()); } It fails as enums.d(25,46): Error: static variable allMembers cannot be read at compile time enums.d(25,21): while evaluating: static assert("a" in allMembers) Is there a solution to this problem?Move the AA declaration to inside the lambda, remove the 'static' from the assert, and fix the condition ("member !in allMembers"), then it will work.
May 02 2014
arturCollision detection should now be complete. https://github.com/nordlow/justd/blob/master/enums.d Superb!
May 02 2014