May 27, 2012
In some code I have created a small bug that can be reduced to something like this, that the D compiler has not caught at compile-time:


enum E1 { A, B }
enum E2 { C, D }
void main() {
    E1[2] a;
    with (E2)
        assert(a[0] == D);
}


Why isn't D able to statically tell when you compare values of different enums?
How much work is implementing this compile-time test inside the D front-end?

Thank you,
bye,
bearophile
May 28, 2012
The *real* question is, why don't you need the "E2" qualifier when you say "D"?
May 28, 2012
On Monday, 28 May 2012 at 05:33:28 UTC, Mehrdad wrote:
> The *real* question is, why don't you need the "E2" qualifier when you say "D"?

well never mind, I need sleep... I didn't see you were using
'with'.
May 28, 2012
On Sunday, May 27, 2012 21:45:22 bearophile wrote:
> In some code I have created a small bug that can be reduced to something like this, that the D compiler has not caught at compile-time:
> 
> 
> enum E1 { A, B }
> enum E2 { C, D }
> void main() {
>      E1[2] a;
>      with (E2)
>          assert(a[0] == D);
> }
> 
> 
> Why isn't D able to statically tell when you compare values of
> different enums?
> How much work is implementing this compile-time test inside the D
> front-end?

If assert(E1.A == E2.D) wouldn't compile, then this is clearly a bug with with. If assert(E1.A == E2.d) compiles, then this behavior is clearly intended. My guess would be that this is a bug with with, but I don't think that I've ever tried to compare two different types of enums like that before, so I'd have to check.

- Jonathan M Davis
May 28, 2012
27.05.2012 23:45, bearophile написал:
> In some code I have created a small bug that can be reduced to something
> like this, that the D compiler has not caught at compile-time:
>
>
> enum E1 { A, B }
> enum E2 { C, D }
> void main() {
> E1[2] a;
> with (E2)
> assert(a[0] == D);
> }
>
>
> Why isn't D able to statically tell when you compare values of different
> enums?
> How much work is implementing this compile-time test inside the D
> front-end?
>
> Thank you,
> bye,
> bearophile

Enumerations are in very poor state in D now. May be, it should be deprecated just like typedef and be library-implemented. Why? Because we do need really strict type/operation checking with enum so one have to write explicitly casts to do non-standard things. The two main enumeration types are:
 * list - must hold only one value, only opAssign and opEqual are allowed, by default nextValue = prevValue + 1 starting with 0
 * flags - must hold superposition of values, like list, but binary operations are also allowed, by default nextValue = prevValue << 1 starting with 1

These also allow finally implement right to!string for flags.

By the way, current enums can be modified to correspond "list" enumeration and flags can be added as library component.

-- 
Денис В. Шеломовский
Denis V. Shelomovskij
May 28, 2012
On 28.05.2012 12:58, Denis Shelomovskij wrote:
> 27.05.2012 23:45, bearophile написал:
>> In some code I have created a small bug that can be reduced to something
>> like this, that the D compiler has not caught at compile-time:
>>
>>
>> enum E1 { A, B }
>> enum E2 { C, D }
>> void main() {
>> E1[2] a;
>> with (E2)
>> assert(a[0] == D);
>> }
>>
>>
>> Why isn't D able to statically tell when you compare values of different
>> enums?
>> How much work is implementing this compile-time test inside the D
>> front-end?
>>
>> Thank you,
>> bye,
>> bearophile
>
> Enumerations are in very poor state in D now. May be, it should be
> deprecated just like typedef and be library-implemented. Why? Because we
> do need really strict type/operation checking with enum so one have to
> write explicitly casts to do non-standard things. The two main
> enumeration types are:
> * list - must hold only one value, only opAssign and opEqual are
> allowed, by default nextValue = prevValue + 1 starting with 0
> * flags - must hold superposition of values, like list, but binary
> operations are also allowed, by default nextValue = prevValue << 1
> starting with 1
>

+1. Well said, hard to add anything ;)

> These also allow finally implement right to!string for flags.
>
> By the way, current enums can be modified to correspond "list"
> enumeration and flags can be added as library component.
>


-- 
Dmitry Olshansky
May 28, 2012
Denis Shelomovskij:

> Enumerations are in very poor state in D now.
> ...
> By the way, current enums can be modified to correspond "list" enumeration and flags can be added as library component.

I think D enums need to become a bit more strict (so you can't equal elements of different enums). Later I think the messy situation with enum attributes needs to be cleared up and improved, removing most of the name clases between the current attributes and enum item names (http://d.puremagic.com/issues/show_bug.cgi?id=4997 ). And later *simple* flags are implementable in Phobos.

First step is to make them less sloppy and more strict, otherwise successive work will be founded on quicksand (but as long as such threads generate no concrete answers from D designers, we are just wasting time here).

In GitHub there are many patches open, applying several of them will reduce many current pain points of using D.

Bye,
bearophile
May 28, 2012
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.

May 28, 2012
On Monday, 28 May 2012 at 08:58:29 UTC, Denis Shelomovskij wrote:
> 27.05.2012 23:45, bearophile написал:
>> In some code I have created a small bug that can be reduced to something
>> like this, that the D compiler has not caught at compile-time:
>>
>>
>> enum E1 { A, B }
>> enum E2 { C, D }
>> void main() {
>> E1[2] a;
>> with (E2)
>> assert(a[0] == D);
>> }
>>
>>
>> Why isn't D able to statically tell when you compare values of different
>> enums?
>> How much work is implementing this compile-time test inside the D
>> front-end?
>>
>> Thank you,
>> bye,
>> bearophile
>
> Enumerations are in very poor state in D now. May be, it should be deprecated just like typedef and be library-implemented. Why? Because we do need really strict type/operation checking with enum so one have to write explicitly casts to do non-standard things. The two main enumeration types are:
>  * list - must hold only one value, only opAssign and opEqual are allowed, by default nextValue = prevValue + 1 starting with 0
>  * flags - must hold superposition of values, like list, but binary operations are also allowed, by default nextValue = prevValue << 1 starting with 1
>
> These also allow finally implement right to!string for flags.
>
> By the way, current enums can be modified to correspond "list" enumeration and flags can be added as library component.

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. See functional languages such as ML for a correct implementation and also Java 5 Enums (similar but with an OO flavor).

The second point is conceptually *wrong* as well - a set of flag values is exactly that - _a set_. The type-safe correct way is to use a set!MyEnum to properly represent this (of course with a specialized implementation for this using bits for performance reasons).
May 28, 2012
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
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home