Мне нужно передать блок из одного метода в другой (я хочу позвонить Rails.cache.fetch
с блоком, переданным моему методу).Передача блока от одного метода к другому
Я могу либо добавить &block
в список параметров, и использовать это, чтобы передать его следующему методу, или я могу создать новый блок и вызвать выход внутри него. Я написал небольшой пример и ориентир:
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
внутри вновь созданного блока?
У вас есть 'Proc' и специализированный' Proc', который является 'lambda', который вы также можете использовать. Метод также является блоком, но не изначально является объектом. Вы можете преобразовать метод, чтобы стать объектом 'Method'. У вас есть выбор, отличный от двух способов передачи блока. Поэтому я думаю, что ваш вопрос несколько неполный. Нет никаких особых соображений, связанных с передачей анонимного блока, за исключением доступа к нему по имени (вне метода, то есть), хотя Procs и lambdas считаются «анонимными», я думаю. – vgoff
'yield' быстрее, действительно. Именно потому, что он менее функциональный. Вы можете только вызывать переданный блок. Вы не можете, например, передать его следующему методу. Ваш тест не имеет смысла, кстати. 'do_something' не использует блок. –
@SergioTulentsev Вы можете передать его, позвонив ему. 'class Array; def my_map; отображение {| е | yield (e)} end end'. – sawa