nested enum

2016-08-24 Thread Illuminati via Digitalmars-d-learn

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

2016-08-24 Thread Mike Parker via Digitalmars-d-learn

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

2016-08-24 Thread Daniel Kozak via Digitalmars-d-learn

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

2016-08-25 Thread Cauterite via Digitalmars-d-learn

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

2016-08-25 Thread Daniel Kozak via Digitalmars-d-learn
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

2016-08-25 Thread Cauterite via Digitalmars-d-learn

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

2016-08-25 Thread Seb via Digitalmars-d-learn

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

2016-08-25 Thread Illuminati via Digitalmars-d-learn

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.


nested enum like template generator

2013-07-15 Thread JS

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.






Re: nested enum like template generator

2013-07-15 Thread Ali Çehreli

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



Re: nested enum like template generator

2013-07-15 Thread JS

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

2013-07-16 Thread Dicebot

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

2013-07-16 Thread Ali Çehreli

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

2013-07-16 Thread Ali Çehreli

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

2013-07-16 Thread JS

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

2013-07-16 Thread Ali Çehreli

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

2013-07-16 Thread Ali Çehreli

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

2013-07-16 Thread JS

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)