选择随机枚举值的简单而安全的方法是什么?
我需要从枚举中选择一个随机值。在一些关于 Nim 的文章中,我找到了这个解决方案:
import random
type Animal = enum
Cat
Dog
Cow
echo rand(0..2).Animal
但这不能很好地扩展:如果在枚举中添加或删除了一些值,我们必须调整上限值。
我们甚至可以得到一个运行时错误:
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]
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]
我正在寻找一种简单的方法来从
安全的枚举1中选择一个随机值,这意味着如果它编译,则保证不会出现RangeDefect或类似的运行时错误。
我也很想知道在上面的例子中是否有一个编译器设置至少生成一个警告。
编译器原则上似乎能够做到这一点:
Animal(5)
? Error: 5 can't be converted to Animal
阅读https://nim-lang.org/docs/random.html关于
- 兰特,兰特,范围[]
- 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]
我认为以下方法之一可以工作,但它们无法编译:
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'
这确实有效,但我猜它不必要地低效,因为它需要分配和填充一个序列:
1我假设没有带孔的枚举,我知道这是
另一个问题。
回答
一个简单的解决方案是使用lowand high:
rand(Animal.low..Animal.high)
使用通用 proc 允许编写rand(Animal):
import random
type Animal = enum
Cat
Dog
Cow
proc rand(T: typedesc): T =
rand(T.low..T.high)
randomize(123)
for _ in 1..6:
echo rand(Animal)
输出:
Cat
Cat
Dog
Cow
Cow
Dog