继续研究ruby元编程那本书。对yield和block机制不是很了解,自己找了个小代码片段。请来反汇编工具分析出来,原来如此。
wu=%w(a b c)
p wu
def foo
yield [1,2,3]
yield 1
end
foo{|v| p v}
下面是反汇编
ruby --dump insns yield1.rb >yield1.txt
== disasm: <RubyVM::InstructionSequence:<main>@yield1.rb>===============
== catch table
| catch type: break st: 0035 ed: 0038 sp: 0000 cont: 0038
|------------------------------------------------------------------------
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] wu
0000 trace 1 ( 1)
0002 putstring "a"
0004 putstring "b"
0006 putstring "c"
0008 newarray 3
0010 setlocal_OP__WC__0 2
0012 trace 1 ( 2)
0014 putself
0015 getlocal_OP__WC__0 2
0017 opt_send_without_block <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>
0019 pop
0020 trace 1 ( 4)
0022 putspecialobject 1
0024 putspecialobject 2
0026 putobject :foo
0028 putiseq foo
0030 opt_send_without_block <callinfo!mid:core#define_method, argc:3, ARGS_SIMPLE>
0032 pop
0033 trace 1 ( 8)
0035 putself
0036 send <callinfo!mid:foo, argc:0, block:block in <main>, FCALL>
0038 leave
== disasm: <RubyVM::InstructionSequence:foo@yield1.rb>==================
0000 trace 8 ( 4)
0002 trace 1 ( 5)
0004 duparray [1, 2, 3]
0006 invokeblock <callinfo!argc:1, ARGS_SIMPLE>
0008 pop
0009 trace 1 ( 6)
0011 putobject_OP_INT2FIX_O_1_C_
0012 invokeblock <callinfo!argc:1, ARGS_SIMPLE>
0014 trace 16 ( 7)
0016 leave ( 6)
== disasm: <RubyVM::InstructionSequence:block in <main>@yield1.rb>======
== catch table
| catch type: redo st: 0002 ed: 0009 sp: 0000 cont: 0002
| catch type: next st: 0002 ed: 0009 sp: 0000 cont: 0009
|------------------------------------------------------------------------
local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] v<Arg>
0000 trace 256 ( 8)
0002 trace 1
0004 putself
0005 getlocal_OP__WC__0 2
0007 opt_send_without_block <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>
0009 trace 512
0011 leave
可以看到所有的秘密:yield对应指令invokeblock,就是普通的回调而已。ruby的所以的元编程技巧都可以用汇编代码看到它的实现原理