digitalmars.D.learn - std.random.uniform for enums
- Anton (13/13) Feb 12 2014 I'm confused about how to use random.uniform to select a member
- Jakob Ovrum (21/34) Feb 12 2014 The problem with using `uniform` for enums is that not all enums
- Frustrated (3/41) Feb 12 2014 Could you not simply select one at random by "name"? Even though
- Anton (6/6) Feb 12 2014 I guess I'm mostly confused because the description for one of
- Adam D. Ruppe (8/11) Feb 12 2014 Oooh, I didn't know it had one of those, the documentation can be
- Anton (5/16) Feb 12 2014 Yeah, the docs aren't the easiest to read, especially coming from
- Anton (3/3) Feb 12 2014 It would be useful if someone added this as an example to the
- Andrej Mitrovic (3/6) Feb 12 2014 My mistake for not adding an example when implementing the function. Her...
- Meta (2/8) Feb 12 2014 Huh, disregard me. I didn't know there was a function for that.
- Jakob Ovrum (5/7) Feb 12 2014 Yeah, and there is apparently already an overload that does that.
- Jakob Ovrum (4/13) Feb 12 2014 It's also worth noting that both the existing std.random.uniform
- Meta (18/66) Feb 12 2014 import std.random, std.stdio, std.traits;
- Adam D. Ruppe (10/11) Feb 12 2014 Yeah, uniform takes two numerical arguments: a min and a max. It
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?
Feb 12 2014
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)); } ---
Feb 12 2014
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:Could you not simply select one at random by "name"? Even though the values of the enum may not be sequential the keys are.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)); } ---
Feb 12 2014
I guess I'm mostly confused because the description for one of the templates of std.random.uniform says "Returns a uniformly selected member of enum E. If no random number generator is passed, uses the default rndGen." So I was wondering why that functionality didn't seem to work as I thought it would. Otherwise, thanks for the workarounds.
Feb 12 2014
On Thursday, 13 February 2014 at 02:52:44 UTC, Anton wrote:I guess I'm mostly confused because the description for one of the templates of std.random.uniform says "Returns a uniformly selected member of enum E.Oooh, I didn't know it had one of those, the documentation can be so hard to read sometimes. Try this then: auto randomAnimal = uniform!Animals(); The enum E there is a compile time argument, so you need the ! in there to pass them. (uniform(Animal) would be trying to send it as a run time argument which doesn't work for types)
Feb 12 2014
On Thursday, 13 February 2014 at 02:59:01 UTC, Adam D. Ruppe wrote:On Thursday, 13 February 2014 at 02:52:44 UTC, Anton wrote:Yeah, the docs aren't the easiest to read, especially coming from Python. But thanks a lot for your help. Using ! does the trick.I guess I'm mostly confused because the description for one of the templates of std.random.uniform says "Returns a uniformly selected member of enum E.Oooh, I didn't know it had one of those, the documentation can be so hard to read sometimes. Try this then: auto randomAnimal = uniform!Animals(); The enum E there is a compile time argument, so you need the ! in there to pass them. (uniform(Animal) would be trying to send it as a run time argument which doesn't work for types)
Feb 12 2014
It would be useful if someone added this as an example to the docs, so that beginners don't end up in the same situation as me in the future.
Feb 12 2014
On 2/13/14, Anton <vizardx gmail.com> wrote:It would be useful if someone added this as an example to the docs, so that beginners don't end up in the same situation as me in the future.My mistake for not adding an example when implementing the function. Here we go: https://github.com/D-Programming-Language/phobos/pull/1932
Feb 12 2014
On Thursday, 13 February 2014 at 02:52:44 UTC, Anton wrote:I guess I'm mostly confused because the description for one of the templates of std.random.uniform says "Returns a uniformly selected member of enum E. If no random number generator is passed, uses the default rndGen." So I was wondering why that functionality didn't seem to work as I thought it would. Otherwise, thanks for the workarounds.Huh, disregard me. I didn't know there was a function for that.
Feb 12 2014
On Thursday, 13 February 2014 at 02:30:47 UTC, Frustrated wrote:Could you not simply select one at random by "name"? Even though the values of the enum may not be sequential the keys are.Yeah, and there is apparently already an overload that does that. Regardless, I wrote a version that has an optimized path for sequential enums: https://gist.github.com/JakobOvrum/8968977
Feb 12 2014
On Thursday, 13 February 2014 at 03:04:06 UTC, Jakob Ovrum wrote:On Thursday, 13 February 2014 at 02:30:47 UTC, Frustrated wrote:It's also worth noting that both the existing std.random.uniform and the one I posted would fail when the base type of the enum has mutable indirection.Could you not simply select one at random by "name"? Even though the values of the enum may not be sequential the keys are.Yeah, and there is apparently already an overload that does that. Regardless, I wrote a version that has an optimized path for sequential enums: https://gist.github.com/JakobOvrum/8968977
Feb 12 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: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.On Thursday, 13 February 2014 at 02:02:38 UTC, Anton wrote:Could you not simply select one at random by "name"? Even though the values of the enum may not be sequential the keys are.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)); } ---
Feb 12 2014
On Thursday, 13 February 2014 at 02:02:38 UTC, Anton wrote:Am I misunderstanding how this function is meant to be used?Yeah, uniform takes two numerical arguments: a min and a max. It returns a value between the two, including the min, but not including the max. So int a = uniform(0, 10); // returns 0,1,2,3,4,5,6,7,8, or 9. You could do a random animal by doing `cast(Animals) uniform(0, 3);`, or getting fancier with reflection stuff... that'd take a few more lines, use __traits(getMember) and __traits(allMembers) to randomize rather than .min and .max because the latter wouldn't handle holes in the values.
Feb 12 2014