View mode: basic / threaded / horizontal-split · Log in · Help
May 27, 2012
Wrong enum comparisons
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
Re: Wrong enum comparisons
The *real* question is, why don't you need the "E2" qualifier 
when you say "D"?
May 28, 2012
Re: Wrong enum comparisons
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
Re: Wrong enum comparisons
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
Re: Wrong enum comparisons
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
Re: Wrong enum comparisons
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
Re: Wrong enum comparisons
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
Re: Wrong enum comparisons
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
Re: Wrong enum comparisons
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
Re: Wrong enum comparisons
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