diary

I like Hatena Star with a text selection.

2023-02-16

defined?の中で代入をすると、バイトコードには変数定義が現れないけれど、変数が定義されると知った。

$ ruby --dump=insns -e 'defined? a=1; p a'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,17)> (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 putself                                                          (   1)[Li]
0001 getlocal_WC_0                          a@0
0003 opt_send_without_block                 <calldata!mid:p, argc:1, FCALL|ARGS_SIMPLE>
0005 leave

# 変数定義はしっかりある
$ ruby -e 'defined? a=1; p a; p binding.local_variables'
nil
[:a]

ruby-jpで「特定のローカル変数への代入がバイトコード上にあらわれないもの」は何があるか、という質問がしばらく前にあったので、それを思い出して挙動を眺めていた。


↑を思い出したきっかけが、コードを読んでいてdefined? yieldがあり、「yieldという名前のメソッドが定義されているかどうかをdefined?で検査できないのでは…?」と思いついたからだった。 これをきっかけにdefined?のドキュメントを読んでいて、ローカル変数のことに思い至った。