Re: nested enum
On Thursday, 25 August 2016 at 01:37:05 UTC, Mike Parker wrote: On Wednesday, 24 August 2016 at 23:04:25 UTC, Illuminati wrote: How can I create nested enum like structures? instead of Enum.X_Y I would like to access like Enum.X.Y Yet I want it to behave exactly as an enum. I just want to not use _ as .'s are better as they express more clearly what I want. struct MyEnum { enum X { Y = 10, Z = 20 } } void main() { import std.stdio; int y = MyEnum.X.Y; writeln(y); } Thanks. I should have thought of that.
Re: nested enum
On Thursday, 25 August 2016 at 11:09:43 UTC, Cauterite wrote: On Thursday, 25 August 2016 at 10:36:21 UTC, Daniel Kozak wrote: Btw, tehre is no need for extra semicolon (`;`) after enum and struct definition Thanks. This forum insists on reminding me every time I write code here. Warning about this is now an enhancement request: https://issues.dlang.org/show_bug.cgi?id=16430
Re: nested enum
On Thursday, 25 August 2016 at 10:36:21 UTC, Daniel Kozak wrote: Btw, tehre is no need for extra semicolon (`;`) after enum and struct definition Thanks. This forum insists on reminding me every time I write code here.
Re: nested enum
Btw, tehre is no need for extra semicolon (`;`) after enum and struct definition Dne 25.8.2016 v 12:23 Cauterite via Digitalmars-d-learn napsal(a): On Wednesday, 24 August 2016 at 23:04:25 UTC, Illuminati wrote: Well those other answers aren't wrong, but I envisioned that you'd have multiple categories within your sub-enums and whatnot, so you'd need something more like this: struct A { enum X { one, two, three, }; enum Y { four = X.max + 1, five, six, }; enum Z { seven = Y.max + 1, eight, nine, }; }; Continuing each enumeration from the end of the previous ensures you won't get any fields with the same values.
Re: nested enum
On Wednesday, 24 August 2016 at 23:04:25 UTC, Illuminati wrote: Well those other answers aren't wrong, but I envisioned that you'd have multiple categories within your sub-enums and whatnot, so you'd need something more like this: struct A { enum X { one, two, three, }; enum Y { four = X.max + 1, five, six, }; enum Z { seven = Y.max + 1, eight, nine, }; }; Continuing each enumeration from the end of the previous ensures you won't get any fields with the same values.
Re: nested enum
And if you need more levels: struct MyEnum { static struct AnotherEnum { enum X { Y = 10, Z = 20 } } } void main() { import std.stdio; int y = MyEnum.AnotherEnum.X.Y; writeln(y); } Dne 25.8.2016 v 03:37 Mike Parker via Digitalmars-d-learn napsal(a): On Wednesday, 24 August 2016 at 23:04:25 UTC, Illuminati wrote: How can I create nested enum like structures? instead of Enum.X_Y I would like to access like Enum.X.Y Yet I want it to behave exactly as an enum. I just want to not use _ as .'s are better as they express more clearly what I want. struct MyEnum { enum X { Y = 10, Z = 20 } } void main() { import std.stdio; int y = MyEnum.X.Y; writeln(y); }
Re: nested enum
On Wednesday, 24 August 2016 at 23:04:25 UTC, Illuminati wrote: How can I create nested enum like structures? instead of Enum.X_Y I would like to access like Enum.X.Y Yet I want it to behave exactly as an enum. I just want to not use _ as .'s are better as they express more clearly what I want. struct MyEnum { enum X { Y = 10, Z = 20 } } void main() { import std.stdio; int y = MyEnum.X.Y; writeln(y); }
nested enum
How can I create nested enum like structures? instead of Enum.X_Y I would like to access like Enum.X.Y Yet I want it to behave exactly as an enum. I just want to not use _ as .'s are better as they express more clearly what I want.
Re: nested enum like template generator
On Tuesday, 16 July 2013 at 21:12:36 UTC, Ali Çehreli wrote: On 07/16/2013 02:01 PM, Ali Çehreli wrote: > On 07/16/2013 01:40 PM, JS wrote: > > It would be nice if we had some way to data globally(in module). > > > > e.g., __ctfestore["name"] = value; > > I would expect model-level objects start their lives after the program > starts running but their initial value can be calculated during compile > time: > > import std.stdio; > import std.conv; > > int[string] ctfestore; > > static this() > { > ctfestore = A!().globalFunc(); > } Ok, I've been silly. That's not CTFE. I meant something like this: static this() { enum initialValue = A!().globalFunc(); ctfestore = initialValue; } And only then I got the problem: > template A() > { > int c; > > int[string] globalFunc() > { > int[string] result; > > void func() > { > for ( ; c < 10; ++c) { Error: static variable c cannot be read at compile time called from here: func() called from here: globalFunc() > result[c.to!string] = c; > } > } > > func(); > return result; > } > } > > void main() > { > writeln(ctfestore); > } > > Prints: > > ["0":0, "4":4, "8":8, "1":1, "5":5, "9":9, "2":2, "6":6, "3":3, "7":7] Ali yes, that error is the bitch that D loves to slap me with constantly when using ctfe's and I have to use wierd methods to get around it. Note that I am mainly talking about string mixins but the issue is that c is a template variable which is a compile time construct that has no real meaning inside a ctfe(if that makes sense). This is why nested functions have to be used... but then if you want global variables(cross-template variables) you need some other technique, if it's even possible. template A() { int c; // doesn't create a variable c for functions in the template to use but tells the template define a variable when used, I guess, as a normal template(not a mixin). That is, I was initially thinking `int c;` created a compile time variable inside the template but it doesn't... c does't even exist until the template is used, but by then, it's too late... specially if the template is used as a string mixin. I think we would need somethign like template A() { template int c; // or possibly internal int c; which defines c as a template variable(not a symbolic expression inserted into code where A is used. here is code that makes it clear: module main; import std.stdio, std.cstream, std.conv; template A() { int c; int foo() { return ++c; } enum A = foo(); // Comment out to change A to a standard template } void main(string[] argv) { alias A!() a; //writeln(a.c, a.foo()); writeln(a); } Note that A is used two different ways. A as a sort of function itself(with return foo() and, if that line is commented out, as a sort of container holding an int and a function. I think this is the confusion that I had not realizing they are two different beasts. When A is acting as a container, foo can use c no problem. When A is acting as a ctfe, foo can't use c. I'm not sure if this is a flaw, bug, or what... I don't see any reason why it can't work both ways, and nesting the template as a function works to solve the compile time error. I think both concepts can be unified by having the compiler implicitly wrap everything inside the template in a function, accept assignments to A, when used as a ctfe. (this may not work well though but a start in the right direction)
Re: nested enum like template generator
On 07/16/2013 02:01 PM, Ali Çehreli wrote: > On 07/16/2013 01:40 PM, JS wrote: > > It would be nice if we had some way to data globally(in module). > > > > e.g., __ctfestore["name"] = value; > > I would expect model-level objects start their lives after the program > starts running but their initial value can be calculated during compile > time: > > import std.stdio; > import std.conv; > > int[string] ctfestore; > > static this() > { > ctfestore = A!().globalFunc(); > } Ok, I've been silly. That's not CTFE. I meant something like this: static this() { enum initialValue = A!().globalFunc(); ctfestore = initialValue; } And only then I got the problem: > template A() > { > int c; > > int[string] globalFunc() > { > int[string] result; > > void func() > { > for ( ; c < 10; ++c) { Error: static variable c cannot be read at compile time called from here: func() called from here: globalFunc() > result[c.to!string] = c; > } > } > > func(); > return result; > } > } > > void main() > { > writeln(ctfestore); > } > > Prints: > > ["0":0, "4":4, "8":8, "1":1, "5":5, "9":9, "2":2, "6":6, "3":3, "7":7] Ali
Re: nested enum like template generator
On 07/16/2013 01:40 PM, JS wrote: > The problem is I can't declare my "global" int variables directly inside > the template. This does make it hard to use the same variable across > multiple functions... > > template A > { > int c; // makes c near useless, can't use it like a normal it... > } Could you please provide complete code. The following works: import std.stdio; import std.conv; template A() { int c; } string func(T)() { string result; alias counter = A!().c; for ( ; counter < 10; ++counter) { result ~= counter.to!string; } return result; } void main() { writeln(func!int()); } Prints: 0123456789 This works as well: import std.stdio; import std.conv; template A() { int c; string func() { string result; for ( ; c < 10; ++c) { result ~= c.to!string; } return result; } } void main() { writeln(A!().func()); } Prints the same: 0123456789 > the error message given obfuscates the reason. What is the error message? > Unfortunately it requires a messy technique to get around by using nested > functions. (The parent function holds the global state of the child > functions) Well, this works as well: import std.stdio; import std.conv; template A() { int c; string globalFunc() { string result; void func() { for ( ; c < 10; ++c) { result ~= c.to!string; } } func(); return result; } } void main() { writeln(A!().globalFunc()); } Again, prints the same: 0123456789 > It would be nice if we had some way to data globally(in module). > > e.g., __ctfestore["name"] = value; I would expect model-level objects start their lives after the program starts running but their initial value can be calculated during compile time: import std.stdio; import std.conv; int[string] ctfestore; static this() { ctfestore = A!().globalFunc(); } template A() { int c; int[string] globalFunc() { int[string] result; void func() { for ( ; c < 10; ++c) { result[c.to!string] = c; } } func(); return result; } } void main() { writeln(ctfestore); } Prints: ["0":0, "4":4, "8":8, "1":1, "5":5, "9":9, "2":2, "6":6, "3":3, "7":7] Ali
Re: nested enum like template generator
On Tuesday, 16 July 2013 at 14:05:38 UTC, Ali Çehreli wrote: On 07/15/2013 10:51 PM, JS wrote: > On Tuesday, 16 July 2013 at 04:37:33 UTC, Ali Çehreli wrote: >> On 07/15/2013 08:43 PM, JS wrote: >> >> > http://dpaste.dzfl.pl/7c8b0ba9 >> > >> > Why the heck can't we use integers in ctfe's? There seems to >> be no >> > simple way to create a counter and this is one of the most >> basic >> > programming constructs to use.. yet with ctfe's it's >> impossible. >> > >> > I'd like each variable in the nested structs to be >> incremented properly. >> >> I did not read the code but just from your description, the separate >> compilation model that D uses would preclude that. For example, >> compilation of a.d would not know anything about the counter that b.d >> has counted during its compilation. >> >> Ali > > Huh? what is a.d and b.d? Yeah, I should have read your code before writing that. My comment is for the general case where a.d and b.d are two separte modules that are compiler separately. I thought that you wanted a counter to continue counting between modules. That wold be nice but require external storage to an ctfe which is a limitation of ctfe's. Ok, at least this post has helped me solve my problem. I guess the issue was the error message given. The problem is I can't declare my "global" int variables directly inside the template. This does make it hard to use the same variable across multiple functions... template A { int c; // makes c near useless, can't use it like a normal it... } solution, one has to use nested functions: template A { string templateScope() { int c; // c now acts like a normal global int value to all nested functions. } } I think I understand why this works and is done this way but the error message given obfuscates the reason. Unfortunately it requires a messy technique to get around by using nested functions. (The parent function holds the global state of the child functions) It would be nice if we had some way to data globally(in module). e.g., __ctfestore["name"] = value; I understand this wouldn't probably work well outside the module since compilation order may be not be consistent. (but maybe __ctfeVolitileStore could be used for cross module storage)
Re: nested enum like template generator
On 07/15/2013 10:51 PM, JS wrote: > On Tuesday, 16 July 2013 at 04:37:33 UTC, Ali Çehreli wrote: >> On 07/15/2013 08:43 PM, JS wrote: >> >> > http://dpaste.dzfl.pl/7c8b0ba9 >> > >> > Why the heck can't we use integers in ctfe's? There seems to >> be no >> > simple way to create a counter and this is one of the most >> basic >> > programming constructs to use.. yet with ctfe's it's >> impossible. >> > >> > I'd like each variable in the nested structs to be >> incremented properly. >> >> I did not read the code but just from your description, the separate >> compilation model that D uses would preclude that. For example, >> compilation of a.d would not know anything about the counter that b.d >> has counted during its compilation. >> >> Ali > > Huh? what is a.d and b.d? Yeah, I should have read your code before writing that. My comment is for the general case where a.d and b.d are two separte modules that are compiler separately. I thought that you wanted a counter to continue counting between modules. > The template transforms a string into a D code string... which is then > string mixed in. The counter and code generation have nothing to do with > the result. A counter is needed in the generation of the code to > generate enum like characteristics. > > It does use recursion, and I could pass a variable that counts the > number of elements but this too would probably not work due to D > bitching about using ints. I must still be in the dark but I seriously doubt that you would have problems incrementing an int in D. > I imagine one could hack D to make it's flawed CTFE system work, to some > degree... like using strings: > > > template inc(string s) > { > string _(string a) > { > if (a == "0") return "1"; > if (a == "1") return "2"; > if (a == "2") return "3"; > if (a == "3") return "4"; > return "0"; > } > enum inc = _(s); pragma(msg, ":"~_(s)); > } > > which is a modulo 4 incrementer. So, CTFE's have the ability to count... > but extremely short sighted that they don't. I imagine can write a whole > template library using strings to emulate ints in ctfe's... what a shame > though... That would be extreme. Ali
Re: nested enum like template generator
On 07/15/2013 08:43 PM, JS wrote: > http://dpaste.dzfl.pl/7c8b0ba9 > > Why the heck can't we use integers in ctfe's? That is false: import std.range; import std.algorithm; import std.conv; import std.stdio; string makeCode(int begin, int end) { auto result = appender!string(`enum made = "`); iota(begin, end) .map!(a => a.to!string) .joiner(", ") .copy(result); result ~= `";`; return result.data; } unittest { assert(makeCode(3, 7) == `enum made = "3, 4, 5, 6";`); } void main() { mixin (makeCode(-3, 3)); writeln(made); } > There seems to be no > simple way to create a counter and this is one of the most basic > programming constructs to use.. That would be pretty limiting, right? > yet with ctfe's it's impossible. I have a feeling that you had something else in mind. > I'd like each variable in the nested structs to be incremented properly. It should be simple to convert the code above to do that. Ali
Re: nested enum like template generator
On Tuesday, 16 July 2013 at 05:51:53 UTC, JS wrote: ... Once again you post a complex and messy snippet and than jump to wrong conclusions. This works: template inc(int i) { enum inc = i + 1; } pragma(msg, inc!3); Integers are treated normally in CTFE/templates, contrary to your last statement. You need to reduce to the real problem.
Re: nested enum like template generator
On Tuesday, 16 July 2013 at 04:37:33 UTC, Ali Çehreli wrote: On 07/15/2013 08:43 PM, JS wrote: > http://dpaste.dzfl.pl/7c8b0ba9 > > Why the heck can't we use integers in ctfe's? There seems to be no > simple way to create a counter and this is one of the most basic > programming constructs to use.. yet with ctfe's it's impossible. > > I'd like each variable in the nested structs to be incremented properly. I did not read the code but just from your description, the separate compilation model that D uses would preclude that. For example, compilation of a.d would not know anything about the counter that b.d has counted during its compilation. Ali Huh? what is a.d and b.d? The template transforms a string into a D code string... which is then string mixed in. The counter and code generation have nothing to do with the result. A counter is needed in the generation of the code to generate enum like characteristics. It does use recursion, and I could pass a variable that counts the number of elements but this too would probably not work due to D bitching about using ints. I imagine one could hack D to make it's flawed CTFE system work, to some degree... like using strings: template inc(string s) { string _(string a) { if (a == "0") return "1"; if (a == "1") return "2"; if (a == "2") return "3"; if (a == "3") return "4"; return "0"; } enum inc = _(s); pragma(msg, ":"~_(s)); } which is a modulo 4 incrementer. So, CTFE's have the ability to count... but extremely short sighted that they don't. I imagine can write a whole template library using strings to emulate ints in ctfe's... what a shame though...
Re: nested enum like template generator
On 07/15/2013 08:43 PM, JS wrote: > http://dpaste.dzfl.pl/7c8b0ba9 > > Why the heck can't we use integers in ctfe's? There seems to be no > simple way to create a counter and this is one of the most basic > programming constructs to use.. yet with ctfe's it's impossible. > > I'd like each variable in the nested structs to be incremented properly. I did not read the code but just from your description, the separate compilation model that D uses would preclude that. For example, compilation of a.d would not know anything about the counter that b.d has counted during its compilation. Ali
nested enum like template generator
http://dpaste.dzfl.pl/7c8b0ba9 Why the heck can't we use integers in ctfe's? There seems to be no simple way to create a counter and this is one of the most basic programming constructs to use.. yet with ctfe's it's impossible. I'd like each variable in the nested structs to be incremented properly.