2016-01-29 16 views
5

, dizinin kimliği korunmuş değildir:Bir proc nesnesi `&`-`ve` gidiş dönüşünde nasıl korunur? bir yönteme geçirmeden zaman <code>*</code> içeren bir dizi uyarısı, o zaman yöntem içinde <code>*</code> ile ondan bir dizi yeniden

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

Ancak, bir dönüş yaparken

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

Nasıl proc nesne

korunur : bir yönteme geçirmeden zaman, o yöntemi içinde & ile bloktan bir proc yeniden & ile bir blok haline proc proc kimliği korunmuş gibi görünüyor? Bir bloğa dönüştürüldüğünde kaybolmuyor mu? Bu garantili bir davranış mı?

+1

Daha takip edilmelidir yani en azından biraz standart davranışı: 'def baz; Proc.new.object_id sonunu koyar; p = -> {}; p.object_id # ⇒ 9708320; baz &p ; # dolayı özel bir sözdizimi kuralına Yani @mudasobwa 9708320' – mudasobwa

+0

olduğunu ⇒. Bir yöntem içinde bir blok içermeyen bir proc oluşturduğunuzda, yönteme geçirilen proc anlamına gelir. – sawa

+0

Biliyorum, teşekkürler. Ben 'Proc.new' aslında bir constructor_ _not anlamına geliyordu. – mudasobwa

cevap

2

Yakut VM bir stackmachine olduğunu. Bir işlevi çağırırken, tüm argümanlarını (self dahil) yığına koyar ve sonra arar.

dizi uyarısı nasıl çalışır

- bu dizi içeriğini alır ve yığını üzerine koyar, sonra fonksiyon çağırır:

> 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 

zaman bir blok, benzer şey olur, ama yakut proc unwrap olmadığı için proc geçen , zaten bir proc.

Ekleme: göre RubySpec en 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 

bu Rubinius ve jruby

+1

Yani bu bu sorunun cevabı size vb MR, JRuby, Rubinius kullanıyor olmanıza bağlıdır anlama geliyor? –

+1

@JoshRumbut rubyspec bu davranışı tanımlar, bu nedenle aynı olmalıdır – Vasfed