Ruby VM is a static machine. When calling a function, it pushes all its arguments (including self ) onto the stack and then calls.
How the splat array works - it takes the contents of the array and puts it on the stack, and then calls the function:
> 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: -1@-1 , 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
When transferring proc in the form of a block, a similar situation occurs, but the ruby ββdoes not need to deploy proc, it is already proc.
Added: according to 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
this is somewhat standardized behavior, so at least Rubinius and jRuby should be followed
source share