enum inheritance?

2011-08-13 Thread mimocrocodil
Hi!

I am want to extend available enum to provide more items to them.

How I can do this job without manual copying of exsisting enum items?


enum inheritance

2013-07-14 Thread JS

It would be nice to be able to use enums in a hierarchical way:

enum colors
{
 enum Red { RedOrange, ... }
 enum Green { GreenBlue, ...}
 enum Blue { BlueYellow, ... }
...
}

which would be the same as the flattened version,

enum colors
{
   Red, RedOrange, ..., Green, GreenBlue, ..., Blue, BlueYellow, 
..., ...

}

but we could dereference such as

colors.Red.RedOrange,
colors.Blue,
colors.Green.GreenBlue,

(This isn't a great example but demonstrates what I would like to 
be able to do)


Is anything like this possible?



Re: enum inheritance?

2011-08-13 Thread Jonathan M Davis
On Saturday, August 13, 2011 23:15:29 mimocrocodil wrote:
> Hi!
> 
> I am want to extend available enum to provide more items to them.
> 
> How I can do this job without manual copying of exsisting enum items?

You can't. An enum has a fixed set of values. You can't extend it in any way, 
shape, or form. You can create other enums, but you can't do anything to add 
new values to the original unless you go and alter the enum declaration to add 
more values. And if you create a new enum, you can't use it in place of the 
old enum, because it's not the same enum and doesn't have the same values.

- Jonathan M Davis


Re: enum inheritance?

2011-08-13 Thread Simen Kjaeraas
On Sun, 14 Aug 2011 01:15:29 +0200, mimocrocodil <4deni...@gmail.com>  
wrote:



Hi!

I am want to extend available enum to provide more items to them.

How I can do this job without manual copying of exsisting enum items?


If what you want is a new enum that contains the values of an existing  
enum,

with some additions, this code will do it:


string EnumDefAsString(T)() if (is(T == enum)) {
string result = "";
foreach (e; __traits(allMembers, T)) {
result ~= e ~ " = T." ~ e ~ ",";
}
return result;
}

template ExtendEnum(T, string s) if (is(T == enum) &&  
is(typeof({mixin("enum a{"~s~"}");}))) {

mixin("enum ExtendEnum {" ~
EnumDefAsString!T() ~ s ~
"}");
}

unittest {
enum bar {
a = 1,
b = 7,
c = 19
}

import std.typetuple;

alias ExtendEnum!(bar, q{ // Usage example here.
d = 25
}) bar2;

foreach (i, e; __traits(allMembers, bar2)) {
static assert( e == TypeTuple!("a", "b", "c", "d")[i] );
}

assert( bar2.a == bar.a );
assert( bar2.b == bar.b );
assert( bar2.c == bar.c );
assert( bar2.d == 25 );

static assert(!is(typeof( ExtendEnum!(int, "a";
static assert(!is(typeof( ExtendEnum!(bar, "25";
}
--
  Simen


Re: enum inheritance?

2011-08-14 Thread Ary Manzana

On 8/13/11 9:42 PM, Simen Kjaeraas wrote:

On Sun, 14 Aug 2011 01:15:29 +0200, mimocrocodil <4deni...@gmail.com>
wrote:


Hi!

I am want to extend available enum to provide more items to them.

How I can do this job without manual copying of exsisting enum items?


If what you want is a new enum that contains the values of an existing
enum,
with some additions, this code will do it:


string EnumDefAsString(T)() if (is(T == enum)) {
string result = "";
foreach (e; __traits(allMembers, T)) {
result ~= e ~ " = T." ~ e ~ ",";
}
return result;
}

template ExtendEnum(T, string s) if (is(T == enum) &&
is(typeof({mixin("enum a{"~s~"}");}))) {
mixin("enum ExtendEnum {" ~
EnumDefAsString!T() ~ s ~
"}");
}


Has D considered introducing string interpolation? That looks very hard 
to read...


Re: enum inheritance

2013-07-14 Thread JS
BTW, the usefulness is to group sub-enums into the same range. 
This would make it easy/efficient to branch over a range in the 
enum:


if (v in colors.Red) { v is a color in red }

instead of

if (v is color.Red || v is color.RedOrange || ...)


Re: enum inheritance

2013-07-14 Thread JS

On Monday, 15 July 2013 at 04:27:42 UTC, JS wrote:
BTW, the usefulness is to group sub-enums into the same range. 
This would make it easy/efficient to branch over a range in the 
enum:


if (v in colors.Red) { v is a color in red }

instead of

if (v is color.Red || v is color.RedOrange || ...)


I guess a more intelligent structure is needed so changes in the 
enum do not break binaries. (although this is already somewhat of 
an issue with enums as changes in order requires a re-compilation)


Re: enum inheritance

2013-07-15 Thread Mike Parker

On Monday, 15 July 2013 at 04:27:42 UTC, JS wrote:
BTW, the usefulness is to group sub-enums into the same range. 
This would make it easy/efficient to branch over a range in the 
enum:


if (v in colors.Red) { v is a color in red }

instead of

if (v is color.Red || v is color.RedOrange || ...)


if( v >= Red && v <= LastRed )


Re: enum inheritance

2013-07-15 Thread JS

On Monday, 15 July 2013 at 07:37:36 UTC, Mike Parker wrote:

On Monday, 15 July 2013 at 04:27:42 UTC, JS wrote:
BTW, the usefulness is to group sub-enums into the same range. 
This would make it easy/efficient to branch over a range in 
the enum:


if (v in colors.Red) { v is a color in red }

instead of

if (v is color.Red || v is color.RedOrange || ...)


if( v >= Red && v <= LastRed )


The problem is if a binary is already compiled and changes are 
made. If a red color is inserted your range has changed. Also, it 
requires you to keep your entries sorted properly. Also, a 
"LastRed" entry is needed and there is no other reason to have it.


Since an int is 4B entries, and that's way more than most will 
use, It think it's better to be able to have the compiler 
partition of the range for you and save "space" for future 
entries. This prevents an addition entry from screwing up 
everything.



e.g.,

enum colors
{
enum Red : 1M { RedOrange, ... }
enum Green : 2M {  ... }
...
}

In this case, one can have up to 1M unordered sub entries(should 
be plenty) and ~4.2k main entries. One could order further,



enum colors
{
enum Red : 1M { enum RedOrange : 10k { }, ... }
enum Green : 2M {  ... }
...
}

Basically the idea is to distribute the elements of enum and sub 
enums in such a way as to maximize space between each entry. This 
allows any binaries using an old version not to crash and burn. 
This does require an estimation of the maximum entries that will 
be used.


I'm particularly thinking of a messaging system where ints can be 
passed around with 10's of thousands of defined messages with 
messages grouped into common functionality(hence the inheritance 
aspect) and adding new messages won't ruin the communications 
between new and old systems.


Nested switch statements can easily and quickly pare down 
determination of a message(not as fast as a flattened hierarchy 
though).




Re: enum inheritance

2013-07-15 Thread Namespace

Maybe this way?


final abstract class Colors
{
enum Red { RedOrange }
enum Green { GreenBlue}
enum Blue { BlueYellow }
}

void main() {
Colors.Red foo = Colors.Red.RedOrange;
assert(foo >= Colors.Red.min && foo <= Colors.Red.max);
}



Re: enum inheritance

2013-07-15 Thread JS

On Monday, 15 July 2013 at 08:20:20 UTC, Namespace wrote:

Maybe this way?


final abstract class Colors
{
enum Red { RedOrange }
enum Green { GreenBlue}
enum Blue { BlueYellow }
}

void main() {
Colors.Red foo = Colors.Red.RedOrange;
assert(foo >= Colors.Red.min && foo <= Colors.Red.max);
}



but RedOrange and GreenBlue have the same value!




Re: enum inheritance

2013-07-15 Thread JS

On Monday, 15 July 2013 at 10:17:08 UTC, JS wrote:

On Monday, 15 July 2013 at 08:20:20 UTC, Namespace wrote:

Maybe this way?


final abstract class Colors
{
enum Red { RedOrange }
enum Green { GreenBlue}
enum Blue { BlueYellow }
}

void main() {
Colors.Red foo = Colors.Red.RedOrange;
assert(foo >= Colors.Red.min && foo <= Colors.Red.max);
}



but RedOrange and GreenBlue have the same value!


Also, Colors.Red is not a value!


Re: enum inheritance

2013-07-15 Thread Dicebot

On Monday, 15 July 2013 at 04:24:59 UTC, JS wrote:

...


I think closest solution you can get is having bunch of private 
enum definitions and combining them into single public one via 
compile-time reflection. Something like "mixin(generateEnum!(Red, 
Green, blue))".


Re: enum inheritance

2013-07-15 Thread Namespace

On Monday, 15 July 2013 at 10:23:22 UTC, JS wrote:

On Monday, 15 July 2013 at 10:17:08 UTC, JS wrote:

On Monday, 15 July 2013 at 08:20:20 UTC, Namespace wrote:

Maybe this way?


final abstract class Colors
{
enum Red { RedOrange }
enum Green { GreenBlue}
enum Blue { BlueYellow }
}

void main() {
Colors.Red foo = Colors.Red.RedOrange;
assert(foo >= Colors.Red.min && foo <= Colors.Red.max);
}



but RedOrange and GreenBlue have the same value!


Also, Colors.Red is not a value!

Then: good luck.


Re: enum inheritance

2013-07-15 Thread JS

On Monday, 15 July 2013 at 11:00:59 UTC, Dicebot wrote:

On Monday, 15 July 2013 at 04:24:59 UTC, JS wrote:

...


I think closest solution you can get is having bunch of private 
enum definitions and combining them into single public one via 
compile-time reflection. Something like 
"mixin(generateEnum!(Red, Green, blue))".


That might solve the partitioning problem and solve part of the 
hierarchical problem but won't allow submember access, e.g., 
colors.red.redorange. It seems like a good start though.


I imagine one could potentially build up a set of nested struct 
with immutable members representing the enums:


final immutable struct Colors
{
final immutable struct Red
{
private immutable int _Red = 1;
immutable int RedOrange = 10001;
alias _Red this; // obviously doesn't work
}

final immutable struct Green
{
immutable int Green = 2;
}

}

but with the glitch on the alias(Colors.Red doesn't work)... 
which sort of throws a kink in the solution making more than a 
2-deep nest useless.


Re: enum inheritance

2013-07-15 Thread Dicebot

On Monday, 15 July 2013 at 13:01:05 UTC, JS wrote:

...


I see. No, unfortunately, I am currently not aware of a way to 
make symbol act as type and and value at the same time.


However it is worth noting that you use plenty of excessive 
attributes. Currently it is not a compiler error but makes code 
much harder to read and confusing. For example, "final" has no 
meaning for structs as they can't be inherited from anyway. 
Duplicating immutable is also excessive because it is transitive.


Re: enum inheritance

2013-07-15 Thread JS

On Monday, 15 July 2013 at 13:47:10 UTC, Dicebot wrote:

On Monday, 15 July 2013 at 13:01:05 UTC, JS wrote:

...


I see. No, unfortunately, I am currently not aware of a way to 
make symbol act as type and and value at the same time.


However it is worth noting that you use plenty of excessive 
attributes. Currently it is not a compiler error but makes code 
much harder to read and confusing. For example, "final" has no 
meaning for structs as they can't be inherited from anyway. 
Duplicating immutable is also excessive because it is 
transitive.



Original I had it as a class. I'm not sure if it matters much 
between a class and a struct though?


In any case, I solved this problem by using an attribute to test 
instead of using isMutable. Obviously this requires adding a 
symbol but not a huge deal.


e.g.,

@Enum immutable struct ...

and hasAttribute(T, Enum) replaces isMutable(T).


Re: enum inheritance

2013-07-15 Thread Dicebot

On Monday, 15 July 2013 at 18:26:26 UTC, JS wrote:
Original I had it as a class. I'm not sure if it matters much 
between a class and a struct though?


It does matter a lot. structs are value types, classes are 
polymorphic reference types. There is a nice summary table in 
docs: http://dlang.org/struct.html , please notice that 
"inheritance" and this "final" applies only for classes.


In any case, I solved this problem by using an attribute to 
test instead of using isMutable. Obviously this requires adding 
a symbol but not a huge deal.


e.g.,

@Enum immutable struct ...

and hasAttribute(T, Enum) replaces isMutable(T).


Yeah, that may work, despite being not that pretty. I personally 
think it is better for now chose some not-that-elegant approach 
in your code, at least until enums will become more robust. 
Currently it tries to workaround some very basic type system 
assumptions, which rarely ends good.


Re: enum inheritance

2013-07-15 Thread JS

On Monday, 15 July 2013 at 19:24:27 UTC, Dicebot wrote:

On Monday, 15 July 2013 at 18:26:26 UTC, JS wrote:
Original I had it as a class. I'm not sure if it matters much 
between a class and a struct though?


It does matter a lot. structs are value types, classes are 
polymorphic reference types. There is a nice summary table in 
docs: http://dlang.org/struct.html , please notice that 
"inheritance" and this "final" applies only for classes.


um, but I'm only using the type at compile time. the immutable 
fields in it all result in compile time literals... the struct 
itself never gets used at run time... so there is no runtime 
difference(or shouldn't be) except maybe a little more wasted 
space with the class unless it is optimized out.



In any case, I solved this problem by using an attribute to 
test instead of using isMutable. Obviously this requires 
adding a symbol but not a huge deal.


e.g.,

@Enum immutable struct ...

and hasAttribute(T, Enum) replaces isMutable(T).


Yeah, that may work, despite being not that pretty. I 
personally think it is better for now chose some 
not-that-elegant approach in your code, at least until enums 
will become more robust. Currently it tries to workaround some 
very basic type system assumptions, which rarely ends good.


I really don't have 10 years to wait for enums to become more 
robust and hope in the way I am trying to use them.


Re: enum inheritance

2013-08-02 Thread bearophile

JS:


It would be nice to be able to use enums in a hierarchical way:

enum colors
{
 enum Red { RedOrange, ... }
 enum Green { GreenBlue, ...}
 enum Blue { BlueYellow, ... }
...
}

which would be the same as the flattened version,

enum colors
{
   Red, RedOrange, ..., Green, GreenBlue, ..., Blue, 
BlueYellow, ..., ...

}

but we could dereference such as

colors.Red.RedOrange,
colors.Blue,
colors.Green.GreenBlue,

(This isn't a great example but demonstrates what I would like 
to be able to do)


Is anything like this possible?


In Ada you can define ranged types, and there is a keyword to 
define their subtypes:


type Day is
   (Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday);

-- Derived types, they are new incompatible with the original:
type Business_Day is new Day range Monday .. Friday;
type Weekend_Day is new Day range Saturday .. Sunday;

-- Subtypes that convert implicitly to their supertype:
subtype Business_Day is Day range Monday .. Friday;
subtype Weekend_Day is Day range Saturday .. Sunday;
subtype Dice_Throw is Integer range 1 .. 6;

The Ada compiler enforces static typing where possible, and uses 
dynamic tests where it can't (and the dynamic tests can be 
disabled with a compiler switch). So if assign a generic integer 
to a Dice_Throw, the Ada compiler performs a run-time test to see 
if it's in the correct range.


Ada code is based on similar things that avoid/catch lot of bugs.

Bye,
bearophile