Інші відповіді досить ґрунтовні, і « Закриття в Рубі» широко висвітлює функціональні відмінності. Мені було цікаво, який метод буде найкращим для методів, які необов'язково приймають блок, тому я написав деякі еталони (виходячи з цього допису Пола Мукура ). Я порівняв три методи:
- & заблокувати підпис методу
- Використовуючи
&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
в інший блок є найшвидшим.
Тим не менш, це результати для мільйона ітерацій, тому не турбуйтеся про це занадто. Якщо один метод робить ваш код зрозумілішим за рахунок мільйонної частки секунди, скористайтеся ним у будь-якому випадку.