可以将随机数生成器传递给它,Array#shuffle
从而使随机播放具有确定性。
例如,在 MRI 1.9.3p327 中:
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 2, 4, 3]
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 2, 4, 3]
但是,没有指定 Random 的随机数生成器实现。正因为如此,Ruby 的其他实现有不同的结果。
在 Rubinius 2.0.0rc1(1.9.3 发布 2012-11-02 JI)中:
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 3, 2, 4]
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 3, 2, 4]
顺便说一句,jruby-1.7.1 使用与 MRI 1.9.3p327 相同的随机数生成器,但这只是偶然,不能保证。
为了实现一致的跨实现确定性随机播放,我想将自定义随机数生成器传递到Array#shuffle
. 我认为这将是微不足道的,但事实证明它相当复杂。
这是我在 MRI 中首先尝试的方法:
class NotRandom; end
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [4, 3, 2, 1]
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [4, 2, 1, 3]
我期待一个NoMethodError
告诉我我需要实现的接口。
有什么见解吗?
更新:
正如@glebm 指出的那样,NotRandom
inheritedKernel#rand
是需要的接口。这很容易解决,但不幸的是没有提供解决方案。
class NotRandom
def rand(*args)
0
end
end
在 RBX 中:
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [1, 2, 3, 4]
在 MRI 中:
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [2, 3, 4, 1]