我需要将一个块从一个方法传递给另一个方法(我想通过传递给我的方法的块调用Rails.cache.fetch
。)
我可以将&block
添加到参数列表中并使用它将其传递给下一个方法,或者我可以创建一个新块并在其中调用yield。我写了一个简短的例子和基准:
require "benchmark"
def with_block(&block)
do_something 'Test', &block
end
def with_yield
do_something('Test') { yield }
end
def do_something(string)
"#{yield} #{string}"
end
n = 5_000_000
Benchmark.bmbm do |x|
x.report("&block") do
n.times { with_block { "Yo" } }
end
x.report("yield") do
n.times { with_yield { "Yo" } }
end
end
&block 3.320000 0.010000 3.330000 ( 3.340438)
yield 1.670000 0.000000 1.670000 ( 1.669504)
--------------------------------- total: 5.000000sec
user system total real
&block 3.270000 0.010000 3.280000 ( 3.275914)
yield 1.680000 0.000000 1.680000 ( 1.682768)
看起来{ yield }
方法要快得多。这是正确的方法吗?由于在新创建的块中调用yield
,我是否有任何遗漏?
答案 0 :(得分:3)
简短回答:始终使用yield
,除非您有充分理由明确引用&block
。
请参阅:Why blocks make ruby methods 439% slower
使用&block
,您可以获得一个具体化的Proc,您可以在其中执行各种stuff并可以移动。但是,使用yield
和隐式块,您只能调用块。
通过使用yield
,解释器可以绕过所有的Proc,因为它知道开发人员将无法使用它;因此它只能保留一个C级结构,而不必设置一个Ruby级别的对象。