其他答案非常彻底,Ruby 中的闭包广泛涵盖了功能差异。我很好奇哪种方法最适合可以选择接受块的方法,所以我写了一些基准测试(离开这个 Paul Mucur 帖子)。我比较了三种方法:
- &block 方法签名
- 使用
&Proc.new
- 包裹
yield
在另一个块中
这是代码:
require "benchmark"
def always_yield
yield
end
def sometimes_block(flag, &block)
if flag && block
always_yield &block
end
end
def sometimes_proc_new(flag)
if flag && block_given?
always_yield &Proc.new
end
end
def sometimes_yield(flag)
if flag && block_given?
always_yield { yield }
end
end
a = b = c = 0
n = 1_000_000
Benchmark.bmbm do |x|
x.report("no &block") do
n.times do
sometimes_block(false) { "won't get used" }
end
end
x.report("no Proc.new") do
n.times do
sometimes_proc_new(false) { "won't get used" }
end
end
x.report("no yield") do
n.times do
sometimes_yield(false) { "won't get used" }
end
end
x.report("&block") do
n.times do
sometimes_block(true) { a += 1 }
end
end
x.report("Proc.new") do
n.times do
sometimes_proc_new(true) { b += 1 }
end
end
x.report("yield") do
n.times do
sometimes_yield(true) { c += 1 }
end
end
end
Ruby 2.0.0p247 和 1.9.3p392 的性能相似。以下是 1.9.3 的结果:
user system total real
no &block 0.580000 0.030000 0.610000 ( 0.609523)
no Proc.new 0.080000 0.000000 0.080000 ( 0.076817)
no yield 0.070000 0.000000 0.070000 ( 0.077191)
&block 0.660000 0.030000 0.690000 ( 0.689446)
Proc.new 0.820000 0.030000 0.850000 ( 0.849887)
yield 0.250000 0.000000 0.250000 ( 0.249116)
在不总是使用时添加显式&block
参数确实会减慢该方法的速度。如果该块是可选的,请不要将其添加到方法签名中。而且,对于传递块,包裹yield
在另一个块中是最快的。
也就是说,这些是一百万次迭代的结果,所以不要太担心。如果一种方法以百万分之一秒为代价使您的代码更清晰,那么无论如何都要使用它。