1行のRubyプログラムを左から順に評価していきます。 これは意図時にデザインしたルールではなく、実装の結果です。
a[0], a[1] = [b, b] のときはそうではありません。
発表者のJeremy Evansさんは、Rubyのバグを大量に直しているコミッターの方です。 そのなかでも面白いバグを初回してくれました。
内容はよくわからなかっかです。
ruby --dump=i
を実行するとRubyのinstructionsを表示することがわかりました。
試しに a = 1
のinstructionsを表示してみます。
ledsun@MSI:/m/c/U/led_l►ruby --dump=i -e 'a = 1' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,5)> (catch: FALSE) local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] a@0 0000 putobject_INT2FIX_1_ ( 1)[Li] 0001 dup 0002 setlocal_WC_0 a@0 0004 leave
表示されている命令の意味はよくわかりません。
a = 2
やb = 1
のinstructionsを表示すると、内容が変わっていることがわかります。
ledsun@MSI:/m/c/U/led_l►ruby --dump=i -e 'a = 2' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,5)> (catch: FALSE) local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] a@0 0000 putobject 2 ( 1)[Li] 0002 dup 0003 setlocal_WC_0 a@0 0005 leave
ledsun@MSI:/m/c/U/led_l►ruby --dump=i -e 'b = 1' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,5)> (catch: FALSE) local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] b@0 0000 putobject_INT2FIX_1_ ( 1)[Li] 0001 dup 0002 setlocal_WC_0 b@0 0004 leave
この機能をつかって、a.b, c[0] = d, e
のinstructionsを表示して、Ruby 3.0から3.2までの変更を説明してくれました。
実際に手元のPCで試してみると、発表と同じように表示されるinstructionsが変わっているのがわかります。
ledsun@MSI:/m/c/U/led_l►ruby -v --dump=i -e 'a.b, c[0] = d, e' ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-linux] == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,16)> (catch: FALSE) 0000 putself ( 1)[Li] 0001 opt_send_without_block <calldata!mid:d, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0003 putself 0004 opt_send_without_block <calldata!mid:e, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0006 newarray 2 0008 dup 0009 expandarray 2, 0 0012 putself 0013 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0015 topn 1 0017 opt_send_without_block <calldata!mid:b=, argc:1, ARGS_SIMPLE> 0019 pop 0020 pop 0021 putself 0022 opt_send_without_block <calldata!mid:c, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0024 putobject_INT2FIX_0_ 0025 topn 2 0027 opt_aset <calldata!mid:[]=, argc:2, ARGS_SIMPLE> 0029 pop 0030 pop 0031 leave
ledsun@MSI:/m/c/U/led_l►ruby -v --dump=i -e 'a.b, c[0] = d, e' ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux] == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,16)> (catch: FALSE) 0000 putself ( 1)[Li] 0001 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0003 putself 0004 opt_send_without_block <calldata!mid:c, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0006 putobject_INT2FIX_0_ 0007 putself 0008 opt_send_without_block <calldata!mid:d, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0010 putself 0011 opt_send_without_block <calldata!mid:e, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0013 newarray 2 0015 dup 0016 expandarray 2, 0 0019 topn 5 0021 swap 0022 opt_send_without_block <calldata!mid:b=, argc:1, ARGS_SIMPLE> 0024 pop 0025 topn 3 0027 topn 3 0029 topn 2 0031 opt_aset <calldata!mid:[]=, argc:2, ARGS_SIMPLE>[CcCr] 0033 pop 0034 pop 0035 setn 3 0037 pop 0038 pop 0039 pop 0040 leave
ledsun@MSI:/m/c/U/led_l►ruby -v --dump=i -e 'a.b, c[0] = d, e' ruby 3.2.0preview2 (2022-09-09 master 35cfc9a3bb) [x86_64-linux] == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,16)> (catch: false) 0000 putself ( 1)[Li] 0001 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0003 putself 0004 opt_send_without_block <calldata!mid:c, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0006 putobject_INT2FIX_0_ 0007 putself 0008 opt_send_without_block <calldata!mid:d, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0010 putself 0011 opt_send_without_block <calldata!mid:e, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0013 newarray 2 0015 dup 0016 expandarray 2, 0 0019 topn 5 0021 swap 0022 opt_send_without_block <calldata!mid:b=, argc:1, ARGS_SIMPLE> 0024 pop 0025 topn 3 0027 topn 3 0029 topn 2 0031 opt_aset <calldata!mid:[]=, argc:2, ARGS_SIMPLE>[CcCr] 0033 pop 0034 pop 0035 setn 3 0037 pop 0038 pop 0039 pop 0040 leave
どうやらJeremy Evansさんはこういうところを直しているみたいです。 instructionsが読めないので、具体的にどうなおしたのかはわかりませんでした。
を読んだら理解できるようになるでしょうか?