如果您将范围作为随机数生成器传递,Array#sample
如何工作?
在这里:
> [*1..10].sample(random: 1..3)
=>9
答案 0 :(得分:6)
根据文档sample(random: rng)
,rng
不是Range
对象,正如您可能想到的那样。 rng
是随机号码生成器。
可选的rng参数将用作随机数生成器。
a = (1..10).to_a
r = Random.new
r2 = r.dup
a1 = a.sample(random: r)
a2 = a.sample(random: r2)
a1 == a2 # => true
该点为#sample
,将其第二个参数作为关键字参数。如果我们使用foo: 12
或rng: (1..2)
之类的内容,则会提供 ArgumentError:unknown keyword:。只有当您为random: <any random number generator>
提供值时,可选参数才可接受。现在,来到你的观点:
r = 1..3
a1 = [*1..10].sample(random: r)
a2 = [*1..10].sample(random: r)
a1 == a2 # => false
当您将第二个参数作为random: r
传递时,r
必须是Random
个对象,或者是响应#rand
的对象。请记住,使用第二个参数,您告诉#sample
,使用您的随机数生成器而不是默认它使用的默认缺少可选参数。
以下是 RNG 的一个自定义实现:
ob = Object.new
def ob.to_int
5000
end
gen_to_int = proc do |max|
ob
end
class << gen_to_int
alias rand call
end
ary = (0...10000).to_a
ary.sample(random: gen_to_int) # => 5000
ary.sample(random: gen_to_int) # => 5000
ary.sample(random: gen_to_int) # => 5000
这将通过可选参数让您了解#sample
。从#test_sample_random
寻找更多示例。
<强>更新强>
如果您将范围作为随机数生成器传递,
Array#sample
如何工作?
要回答这个问题,我会接受TracePoint
课程的帮助。
trace = TracePoint.new(:c_call) do |tp|
p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
end
trace.enable do
[1,2,3,4,5,66,4].sample(random: 1..3)
end
# >> [6, Array, :sample, :c_call]
# >> [6, Kernel, :rand, :c_call]
# >> [6, Kernel, :respond_to_missing?, :c_call]
因此,从上面的调用堆栈,您可以看到 - Array#sample
方法已被调用。现在在内部,Ruby在Kernel#rand
对象上调用了Range
。现在,(1..3).respond_to?
返回false
(因为#rand
- 它是Range
的a_private_实例方法),这就是为什么最后调用#respond_to_missing?
方法的原因做这个工作。