std.random.uniform for enums

Meta jared771 at gmail.com
Wed Feb 12 19:08:09 PST 2014


On Thursday, 13 February 2014 at 02:30:47 UTC, Frustrated wrote:
> On Thursday, 13 February 2014 at 02:14:02 UTC, Jakob Ovrum 
> wrote:
>> On Thursday, 13 February 2014 at 02:02:38 UTC, Anton wrote:
>>> I'm confused about how to use random.uniform to select a 
>>> member of an enum.
>>>
>>> Say I have an enum like
>>>
>>>   enum Animals
>>>   {
>>>     cat  = 0,
>>>     dog = 1,
>>>     chimpanzee = 2
>>>   }
>>>
>>> I want to select a random animal. So far I've been trying to 
>>> do uniform(Animals), but every time I try to compile that, I 
>>> get a "does not match any function template declaration" 
>>> error.
>>>
>>> Am I misunderstanding how this function is meant to be used?
>>
>> The problem with using `uniform` for enums is that not all 
>> enums are sequential without holes, which would make the 
>> `uniform` implementation quite non-trivial if it were to try 
>> to handle enums generically.
>>
>> If you know your enum is sequential and doesn't have any 
>> holes, assume responsibility for that fact with a cast:
>>
>> ---
>> enum Animals
>> {
>> 	cat = 0,
>> 	dog = 1,
>> 	chimpanzee = 2
>> }
>>
>> void main()
>> {
>> 	import std.random, std.stdio;
>>
>> 	foreach(immutable _; 0 .. 10)
>> 		writeln(cast(Animals)uniform!"[]"(Animals.min, Animals.max));
>> }
>> ---
>
> Could you not simply select one at random by "name"? Even though
> the values of the enum may not be sequential the keys are.

import std.random, std.stdio, std.traits;

enum Animals
{
	dog = "dog",
	cat = "cat",
	fox = "fox",
	cow = "cow",
}

void main()
{
	auto animals = [EnumMembers!Animals];
	auto rnd = uniform!"[)"(0, animals.length);
	writeln(animals[rnd]);
}

You have to wrap the EnumMembers template in an array, because 
tuples can only be sliced at compile-time, and uniform doesn't 
work at compile time.


More information about the Digitalmars-d-learn mailing list