May 28, 2012
Andrei Alexandrescu:

> I do agree that it's wrong to _conflate_ the enumerated value with it ordinal, so in this program neither comparison should compile without an explicit cast:
>
> enum E1 { A, B }
> enum E2 { C, D }
>
> void main() {
>     E1 a;
>     assert(a == 0);
>     assert(a == E2.C);
> }
>
> The first one is probably difficult to disallow at this time,

I filed this first problem in 2010-03 (I have not filed the Enum1==Enum2 problem yet):
http://d.puremagic.com/issues/show_bug.cgi?id=3999

This is a small breaking change, but it doesn't introduce bugs in already written code, it turns into compile-time errors code that currently compiles. I think the usual way to solve this compile-time error is to use a cast (or sometimes use this safe to!() enhancement: http://d.puremagic.com/issues/show_bug.cgi?id=8143 ).


C++11 has "solved" this compatibility problem creating another kind of enum, referred as "enum class":

enum class Foo { V1 = 10 };
int main() {
    int b = Foo::V1 == 10;
}


test.cpp: In function 'int main()':
test.cpp:3: error: no match for 'operator==' in '(Foo)10 == 10'
test.cpp:3: note: candidates are: operator==(int, int) <built-in>

The disadvantage of doing this is the complexity increase of the language.

I don't know how do you estimate how much difficult is to perform small breaking changes in the language.

Bye,
bearophile
May 28, 2012
On Monday, 28 May 2012 at 13:47:47 UTC, Andrei Alexandrescu wrote:
> On 5/28/12 8:19 AM, foobar wrote:
>> I have to loudly object to this definition. Given a typical enumeration
>> such as:
>> enum color {Blue, Green, Red};
>> Who's to say that Blue must equal 0? This is conceptually plain *wrong*.
>>
>> A conceptually correct enumeration must NOT expose such implementation
>> details as the very poor C/D style enums do.
>
> Depends on what the concept is. The archetype for "enumerating" is natural numbers, and in that view there's nothing wrong to attach a natural ordinal to each element of an enumeration.
>
> I do agree that it's wrong to _conflate_ the enumerated value with it ordinal, so in this program neither comparison should compile without an explicit cast:
>
> enum E1 { A, B }
> enum E2 { C, D }
>
> void main() {
>     E1 a;
>     assert(a == 0);
>     assert(a == E2.C);
> }
>
> The first one is probably difficult to disallow at this time, but the second one almost always indicates a bug, confusion, or abuse on the user side. We should disallow it.
>
>> See functional languages
>> such as ML for a correct implementation and also Java 5 Enums (similar
>> but with an OO flavor).
>
> I've always found it amusing to watch what a kitchen sink Java enumerations have become. It's as if someone said, "so you complain Java doesn't have enum? I'll give you enum!" I think we shouldn't copy that design.
>
>
> Andrei

It depends on what exactly the general concept is, is this a predefined set of values or is it an ordered list. I'd argue that the set is more general and we shouldn't force an ordering when one isn't strictly required. Of course, the programmer should be able to add an ordering when it's required.

How to implement an order:
IMO casts usually indicate code smell.
I think something like Color.Red.ordinal states the intention much better than a cast.

Could you please explain the issues you see in Java's Enum that cause you to reject such a design?
May 28, 2012
Am Mon, 28 May 2012 13:48:23 +0200
schrieb "Araq" <rumpf_a@web.de>:

> Pascal got type safe enums and sets of enums (aka "flags") right in the 60ies. Too bad not even Ada copied this nice feature. Fortunately, Nimrod does.

Yes, I really like Pascal for that feature. Actually it is a mix of features I miss from Pascal in D:

1. Ranged ordinal types

  type Month = 1 .. 12;
  type AsciiLower = 'a' .. 'z';
  type Hours = 0 .. 24;

As far as I remember it, the compiler chooses the optimal ordinal type derived from the start and end constant. It is a form of self-documenting code and it could work nice with "checked integers", if they are ever implemented in D.


2. Enumerations

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

Ord(x) gives the ordinal value of an enumeration variable, e.g. neither implicit conversion to integer types nor casts, but a language defined, clean way to convert from enums to their inherent integer representation.


3. Sets

I'd like to start with the enumeration for the days of a week, because I think both Pascal and D look intuitive here:

  Pascal:
    type Day = ( Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday );
    var weekday : Day;
    weekday = Monday;
    weekday = Succ(weekday); // Tuesday
  D:
    enum Day { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }
    Day weekday = Monday;
    weekday++; // Tuesday

But D lacks proper sets, which turn any enumeration into a set:

    type
      DaySet = set of Day;

Note how Pascal naturally maps the enum values (0 through 6) to 1, 2, 4, 8, 16, 32 and 64 internally, while in C or D you need to do this manually or by importing a module that offers a template solution. Further you can apply the typical operators to sets:

    var
      workdays : DaySet;
    workdays = [ Monday .. Friday ];  // pretty nice shortcut to set a range of flags
    if Monday in workdays then ...    // check if set contains a value
    weekdays = weekdays + [ Monday, Sunday ] // union (adds Sunday)
    weekdays = weekdays - [ Monday, Sunday ] // complement (removes Monday)
    weekdays = weekdays * [ Monday, Sunday ] // intersection (leaves Monday)
    // (in)euqality, subset and superset are also implemented

I think flag sets are needed often enough (file open modes, drawing hints, enabled features) to warrant that feature and they enable some programming styles that are awkward with what C gives you at hand.


123. All these integrate nicely with each other

Create an array that holds a value of 0 to 24 for each week day:

  var hoursPerDay : array[Day] of Hours;
  hoursPerDay[Monday] = 8;

In general I had a good experience with Pascal when it comes to defining and checking flags.

-- 
Marco

May 28, 2012
On 5/28/12 1:07 PM, foobar wrote:
> It depends on what exactly the general concept is, is this a predefined
> set of values or is it an ordered list. I'd argue that the set is more
> general and we shouldn't force an ordering when one isn't strictly
> required. Of course, the programmer should be able to add an ordering
> when it's required.

Ascribing ordinal values is not ordering.

> How to implement an order:
> IMO casts usually indicate code smell.
> I think something like Color.Red.ordinal states the intention much
> better than a cast.

Well ordinal could always be a function that does the cast...

> Could you please explain the issues you see in Java's Enum that cause
> you to reject such a design?

Too big for what it does. Not worth getting into details as I don't have a strong opinion or one of much consequence.

At the end of the day, it is fairly clear to me that D's enum is in no interesting point on the convenience/safety tradeoff scale, and doesn't offer anything worth its presence in the language. It's just a bit less broken than typedef, which was just egregious. No surprise there - aspects of the language that received attention (e.g. floating point) turned out well whereas those that didn't (either through incomplete analysis or inheriting a bad design) turned out rather badly. I'd put typedef (good thing it's gone), lazy, and enum in the latter category.


Andrei
May 28, 2012
On Monday, May 28, 2012 14:21:14 Andrei Alexandrescu wrote:
> On 5/28/12 1:07 PM, foobar wrote:
> > It depends on what exactly the general concept is, is this a predefined set of values or is it an ordered list. I'd argue that the set is more general and we shouldn't force an ordering when one isn't strictly required. Of course, the programmer should be able to add an ordering when it's required.
> 
> Ascribing ordinal values is not ordering.
> 
> > How to implement an order:
> > IMO casts usually indicate code smell.
> > I think something like Color.Red.ordinal states the intention much
> > better than a cast.
> 
> Well ordinal could always be a function that does the cast...
> 
> > Could you please explain the issues you see in Java's Enum that cause you to reject such a design?
> 
> Too big for what it does. Not worth getting into details as I don't have a strong opinion or one of much consequence.
> 
> At the end of the day, it is fairly clear to me that D's enum is in no interesting point on the convenience/safety tradeoff scale, and doesn't offer anything worth its presence in the language. It's just a bit less broken than typedef, which was just egregious. No surprise there - aspects of the language that received attention (e.g. floating point) turned out well whereas those that didn't (either through incomplete analysis or inheriting a bad design) turned out rather badly. I'd put typedef (good thing it's gone), lazy, and enum in the latter category.

enum does need some work, but I think that the fact that it can be both built- in types such as int as well as user-defined structs is great. It essentially gives us the best of both worlds (basic enums such as in C/C++ and more complex types as in Java). It's some of the minor details where things tend to not work as well as would be nice (e.g. some of the arithmetic that's considered legal on enums which are integral values).

- Jonathan M Davis
May 28, 2012
On 5/28/12 2:37 PM, Jonathan M Davis wrote:
> enum does need some work, but I think that the fact that it can be both built-
> in types such as int as well as user-defined structs is great. It essentially
> gives us the best of both worlds (basic enums such as in C/C++ and more
> complex types as in Java). It's some of the minor details where things tend to
> not work as well as would be nice (e.g. some of the arithmetic that's
> considered legal on enums which are integral values).

I agree it is possible to fix enum.

Andrei


May 28, 2012
Andrei Alexandrescu:

> I do agree that it's wrong to _conflate_ the enumerated value with it ordinal,

> I agree it is possible to fix enum.

Thank you for your answers Andrei. I have filed an enhancement request:
http://d.puremagic.com/issues/show_bug.cgi?id=8157

Issue 8157 is a subset of issue 3999, so they don't interfere with each other in Bugzilla.

I'd like to receive a comment from Walter :-)

Bye,
bearophile
January 14, 2017
On Monday, 28 May 2012 at 21:01:43 UTC, bearophile wrote:
> Andrei Alexandrescu:
>
>> I do agree that it's wrong to _conflate_ the enumerated value with it ordinal,
>
>> I agree it is possible to fix enum.
>
> Thank you for your answers Andrei. I have filed an enhancement request:
> http://d.puremagic.com/issues/show_bug.cgi?id=8157
>
> Issue 8157 is a subset of issue 3999, so they don't interfere with each other in Bugzilla.
>
> I'd like to receive a comment from Walter :-)
>
> Bye,
> bearophile

Alright, ~5 years have passed and no response has been heard so I think it's right about time to get the ball rolling (again).
DMD's PR #6444 implements what's proposed in bugzilla 6227 and that's IMO a solid first step in the right direction.
Feel free to continue the discussion here or on the GH issue.
January 14, 2017
On Monday, 28 May 2012 at 13:47:47 UTC, Andrei Alexandrescu wrote:
> On 5/28/12 8:19 AM, foobar wrote:
>> See functional languages such as ML for a correct implementation and also Java 5 Enums (similar but with an OO flavor).
>
> I've always found it amusing to watch what a kitchen sink Java enumerations have become. It's as if someone said, "so you complain Java doesn't have enum? I'll give you enum!" I think we shouldn't copy that design.

 I could never wrap my head around how the Java Enum/Class was suppose to work or why.

 Also couldn't figure why they wouldn't have a simple structure i could pass around that held data by itself without creating a class from it.
1 2
Next ›   Last »