2016-01-29 21 views
5

當我將它傳遞給一個方法時圖示與*陣列,然後重建從它的陣列與所述方法中*,不保留在陣列的身份:如何在`&`-`&`往返中保存一個proc對象?

a = [] 
a.object_id # => 69846339548760 
def bar *a; a.object_id end 
bar(*a) # => 69846339537540 

然而,當我轉PROC與&塊將它傳遞給方法的情況下,然後重建從塊與所述方法中&一個PROC,該PROC的身份似乎被保留:

pr = ->{} 
pr.object_id # => 69846339666160 
def foo ≺ pr.object_id end 
foo(&pr) # => 69846339666160 

是如何PROC對象保留嗎?它被轉換爲塊時不會丟失嗎?這是一種保證行爲嗎?

+1

更:'高清巴茲;放置Proc.new.object_id結束; p = - > {}; p.object_id#⇒9708320; baz &p ;#⇒9708320' – mudasobwa

+0

@mudasobwa這是由於特殊的語法約定。當你在一個方法內創建一個沒有塊的過程時,它指向傳遞給該方法的過程。 – sawa

+0

我知道,謝謝。我的意思是說'Proc.new'實際上不是構造函數。 – mudasobwa

回答

2

Ruby VM是一個堆棧機器。當調用一個函數時,它將其所有參數(包括self)放到堆棧上,然後調用。

陣列圖示如何工作 - 它需要數組的內容並把它壓入堆棧,然後調用函數:

> puts RubyVM::InstructionSequence.compile("a = []; func *a").disasm 
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: [email protected], kwrest: -1]) 
[ 2] a   
0000 trace   1            ( 1) 
0002 newarray   0 
0004 setlocal_OP__WC__0 2 
0006 putself   
0007 getlocal_OP__WC__0 2 
0009 splatarray  false 
0011 opt_send_without_block <callinfo!mid:func, argc:1, ARGS_SPLAT|FCALL> 
0013 leave 

當傳遞PROC作爲一個塊,類似的事情發生,但是Ruby沒有解開PROC ,它已經是一個proc。

補充:按RubySpec的https://github.com/ruby/spec/blob/master/core/proc/block_pass_spec.rb

def revivify; Proc.new; end 

it "remains the same object if re-vivified by the target method" do 
    p = Proc.new {} 
    p2 = revivify(&p) 
    p.object_id.should == p2.object_id 
    p.should == p2 
end 

這樣比較規範的行爲,所以至少應遵循Rubinius和JRuby的

+1

那麼這是否意味着這個問題的答案取決於你是否使用MRI,JRuby,Rubinius等? –

+1

@JoshRumbut ruby​​spec定義了這種行爲,所以它應該是相同的 – Vasfed

相關問題