enum
Chad Joan
chadjoan at gmail.com
Thu Apr 10 07:03:19 PDT 2014
On Tuesday, 8 April 2014 at 19:08:45 UTC, Andrei Alexandrescu
wrote:
> (moving http://goo.gl/ZISWwN to this group)
>
> ...
>
>
> Andreiu
Honestly, my biggest issues with enums are name-qualification
followed by stringizing.
When I say name-qualification, I mean this:
File myFile;
myFile.open("foobar.txt",
FileAccess.READ |
FileAccess.WRITE );
Things get long and start to wrap due to enums always requiring
full name qualification. This is a mild example; it gets worse
pretty easily.
I'd much rather write:
File myFile;
myFile.open("foobar.txt", READ | WRITE );
It should be possible, because the argument's context is of the
(hypothetical) FileAccess enum type. It should be unambiguous
that I intend to use FileAccess's "READ" symbol there, and not
some other symbol from module scope.
I find myself using a module like this:
http://dpaste.dzfl.pl/9b97c02a26fd
And writing my enums like this:
mixin dequalifyEnum!FileAccess;
mixin toStringifyFlags!FileAccess;
enum FileAccess : int
{
READ = (1 << 0),
WRITE = (1 << 1),
}
It is essentially a reimplementation of the X-macro pattern from
C, but using CTFE+mixins to accomplish the same thing in D.
It expands to something like this:
alias FileAccess.READ READ;
alias FileAccess.WRITE WRITE;
import std.exception : assumeUnique;
string toString(FileAccess val)
{
char[] result = "FileAccess{".dup;
if ( val & FileAccess.READ )
result ~= "READ|";
if ( val & FileAccess.WRITE )
result ~= "WRITE|";
if ( result[$-1] == '|' )
result[$-1] = '}';
else
result ~= "}";
return assumeUnique(result);
}
enum FileAccess : int
{
READ = (1 << 0),
WRITE = (1 << 1),
}
I feel that this approach is bad, because it relies on the
library writer to attach the goodies to the enum. It also
exposes the enum symbols at module-level, which seems icky to
many people. I still find it worthwhile because I dislike
line-wrapping and can always disambiguate symbols by prepending
the module name.
I feel like the following should happen:
File myFile;
// Fine!
myFile.open("foobar.txt", READ | WRITE );
// Fine!
myFile.open("foobar.txt",
FileAccess.READ |
FileAccess.WRITE );
// ERROR: READ is not accessible in this scope.
int someInteger = READ;
// Maybe OK, depending on how strict you want to be.
// It is fairly explicit, after all.
int someInteger = FileAccess.READ;
// Fine! The enum's scope is inferred from context.
FileAccess someInteger = READ | WRITE;
More information about the Digitalmars-d
mailing list