Другие ответы довольно полны, и Замыкания в Ruby подробно охватывают функциональные различия. Мне было любопытно, какой метод лучше всего подойдет для методов, которые , необязательно принимают блок, поэтому я написал несколько тестов (выход из этого сообщения Пола Мукура ). Я сравнил три метода:
- & блок в сигнатуре метода
- Использование
&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
в другом блоке является самой быстрой.
Тем не менее, это результаты для миллиона итераций, так что не беспокойтесь об этом слишком сильно. Если один метод делает ваш код более понятным за счет миллионной доли секунды, все равно используйте его.