I needed to choose a random value from an enum. In some article about Nim I found this solution:
import random
type Animal = enum
Cat
Dog
Cow
echo rand(0..2).Animal
But this doesn't scale well: If some values are added to or removed from the enum, we have to adjust the upper number.
We can even get a runtime error:
import random
type Animal = enum
Cat
Dog
randomize(123)
while true:
echo rand(0..2).Animal
Cat
Cat
Dog
…/example.nim(10) example
…/.choosenim/toolchains/nim-1.4.4/lib/system/fatal.nim(49) sysFatal
Error: unhandled exception: value out of range: 2 notin 0 .. 1 [RangeDefect]
I am looking for a simple way to choose a random value from an enum1 that is safe, meaning that if it compiles, it is guaranteed that there will be no RangeDefect
or similar runtime error.
I would also be interested to know if there is a compiler setting that generates at least a warning that in the above example.
The compiler seems to be capable of this in principle:
echo Animal(5)
→ Error: 5 can't be converted to Animal
After reading in https://nim-lang.org/docs/random.html about
- rand,Rand,range[]
- rand,Rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]
- rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]
- rand,typedesc[T]
I thought that one of the following could work, but they don't compile:
rand(Animal)
→ Error: type mismatch: got <type Animal>
rand(range(Animal))
→ Error: type mismatch: got <type Animal> but expected 'range = range (None)'
rand(range[Animal])
→ Error: expected range
rand(Slice[Animal])
→ Error: type mismatch: got <type Slice[example.Animal]>
rand(Slice(Animal))
→ Error: type mismatch: got <type Animal> but expected 'Slice = CompositeTypeClass'
This does work, but I guess it is unnecessarily inefficient, because it needs to allocate and fill a sequence:
import sequtils
echo sample(Animal.toSeq)
1I'm assuming enums without holes, which I'm aware are another issue.
Aucun commentaire:
Enregistrer un commentaire