Array#sample如果你通过一个范围作为随机数发生器,如何工作?在这里:
> [*1..10].sample(random: 1..3)
=>9
Run Code Online (Sandbox Code Playgroud)
根据文档,您可能不会想象sample(random: rng),rng它不是RangeObject.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
Run Code Online (Sandbox Code Playgroud)
关键是#sample,将其第二个参数作为关键字参数.如果我们使用类似foo: 12or的东西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
Run Code Online (Sandbox Code Playgroud)
当您传递第二个参数时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
Run Code Online (Sandbox Code Playgroud)
这会给你的理解有关#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]
Run Code Online (Sandbox Code Playgroud)
因此,从上面的调用堆栈中,您可以看到 - Array#sample方法已被调用.现在在内部,Ruby调用Kernel#rand了Range对象.现在,(1..3).respond_to?返回false(因为#rand- 它是a_private_实例方法Range),这就是为什么finally #respond_to_missing?方法被调用来完成这项工作的原因.
| 归档时间: |
|
| 查看次数: |
744 次 |
| 最近记录: |