enum

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Tue Apr 8 12:08:46 PDT 2014


(moving http://goo.gl/ZISWwN to this group)

On 4/7/14, 3:41 PM, w0rp wrote:
> Yeah, I've seen this happen before. I think we could actually introduce
> a little more type safety on enums without a great deal of breakage. It
> would be nice to have a final switch give you as much of a guarantee
> about what it's doing as it can.

People use enums for things such as:

1. A discrete set of categorical values:

enum State { initial, waiting, running, done }

That's probably the most common use, and the one that prompted the 
moniker "enum(eration)".

On these, virtually no arithmetic makes any sense. At most, some notion 
of State successor(State) and State predecessor(State) may be sensible. 
It would return the next/previously naturally occurring discrete value, 
and would either throw, assert, or saturate at limits.

2. A collection of power-of-two flags that can be combined with "or" and 
picked apart with "and".

enum AccountFlags { active = 1, overdrawn, hasDiscount = 4, primary = 8 }

Often, people who define these enums offer names for 
frequently-encountered combinations of these flags:

enum AccountFlags { active = 1, overdrawn, hasDiscount = 4, primary = 8, 
regular = active | primary }

For these kinds of flags, arithmetic doesn't make sense, only bitwise 
operations: "|", "&", "^", and "~". A small algebra would be defined for 
these operations.

3. A discrete set of categorical values, not all of which are named:

enum UserID : ulong { nobody, expired = ulong.max }

There would be no arithmetic/logic for such enums - they are only to 
express categories. Comparisons for equality are needed; comparisons for 
inequality may or may not be needed.

4. A "clone" of a type (usually numeric) that's generally used as a 
helper for better typing.

enum Kilogram : double {}
enum Percent {}

All usual arithmetic is supposed to work. The enum acts as a subtype of 
its base type.

5. Various combinations of the above, for example flags combined with masks:

enum AccountFlags { codeMask = 7, active = 8, overdrawn = 16, 
hasDiscount = 32, primary = 64 }

(The account would start with a 3-bit code.) For such complex/irregular 
uses it may make sense to require casting to the base type of the enum 
before carrying general operations.

==========================

The current design is loose enough to accommodate all of the above uses, 
probably too loose because it allows a bunch of nonsensical code to 
compile. There are several questions to ask ourselves:

1. Is the current design damaging enough (= allows enough wrong/buggy 
code to pass through) to warrant a breaking tightening?

2. To what extent can library-based approaches help?

3. What is the priority of improving enums in the larger picture of 
other things we must do?


Andreiu


More information about the Digitalmars-d mailing list