I have taken to selecting random values from enums like so:
import std.random : uniform;
import std.stdio : writefln;
import std.conv;
enum E {A, B, C}
int main(){
auto select = cast(E)uniform(to!int(E.min), to!int(E.max));
writefln("select %s", select);
return 0;
}
This is surprisingly verbose, and prone to issues if any enum members take values outside the default (or larger than int).
Ideally I would take a range that represents the elements of the enum, and provide this to randomSample. However, this doesn’t appear to be possible.
Is there a more idiomatic way to select a random value from an enum in D?
EDIT:
Using the answer provided by fwend, here is a template function that achieves what I want:
T RandomEnumElement(T)() if (is(T == enum)){
auto members = [EnumMembers!T];
return members[(uniform(0, members.length))];
}
Edit: if you need to use the enum values more than once, you can store them in a static immutable array first, otherwise the array will be built every time. That also allows you to get rid of the magic number 3.
Edit 2: As pointed out by Idan Arye, the template could be even terser:
Edit 3: tgehr has suggested the following solution, which would build the lookup table once at compile time and avoid GC allocation altogether: