2016-04-20 189 views
1

我需要將塊從一種方法傳遞給另一種方法(我想調用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

你有'Proc',以及''lambda'專用的'Proc',你也可以使用它。 方法也是一個塊,但最初不是一個對象。你可以將一個方法轉換成一個'Method'對象。 你有更多的選擇,而不僅僅是通過一個塊的兩種方式。所以我認爲你的問題有些不完整。 傳遞一個匿名塊沒有什麼特別的考慮,除了沒有通過名字訪問它(在方法之外),儘管Procs和lambdas都被認爲是「匿名的」。 – vgoff

+0

確實,'yield'的速度更快。正因爲它的功能較差。您只能調用傳遞的塊。例如,你不能將它傳遞給下一個方法。順便說一句,你的測試沒有意義。 'do_something'不使用該塊。 –

+0

@SergioTulentsev你可以通過調用它來傳遞它。 'class Array; def my_map;地圖{| E |產量(e)}末端「。 – sawa

回答

3

簡短回答:請始終使用yield,除非您有充分理由明確引用&block

參見:Why blocks make ruby methods 439% slower

隨着&block,你得到一個具體化的PROC上,你可以做各種stuff,哪些是你可以左右移動。但是,對於yield和一個隱式塊,您僅限於調用塊。

通過使用yield,解釋程序可以繞過所有的過程,因爲它知道開發人員將無法使用它;因此它可以只保留一個C級結構,而不必設置一個Ruby級別的對象。

+0

我明白爲什麼產量比明確提及'&block'更快。有沒有更好的方法將塊從一種方法傳遞到另一種方法,期望從一個新塊中調用「yield」? – xx77aBs

+0

如果你有一個很好的理由來獲得性能打擊,那麼你可以明確地參考'&block'。 (然後,您只需使用'block.call',而不是'yield'。)或者,您可以考慮使用的另一個技巧是「Kernel#block_given?」:http://apidock.com/ruby/Kernel/block_given%3F - - 可以在沒有明確的'&block'聲明的情況下使用。 –

相關問題