[ruby-list:50583] Re: [質問] 変数pが定義されている時のabsの動作について
From:
dogatana <dogatana@...>
Date:
2017-09-05 23:06:36 UTC
List:
ruby-list #50583
こんにちは。 rubyがどのように解釈しているかはrubyに聞くのが一番ということで、 次のコードを考えてみました。 ~~~ iseq = RubyVM::InstructionSequence.compile(<<END) p (-1).abs p = 10 p (-1).abs END puts iseq.disasm ~~~ 結果は ~~~ == disasm: #<ISeq:<compiled>@<compiled>>================================ local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] p # p (-1).abs 0000 trace 1 ( 1) 0002 putself 0003 putobject -1 0005 opt_send_without_block <callinfo!mid:abs, argc:0, ARGS_SIMPLE>, <callcache> 0008 opt_send_without_block <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0011 pop # p = 10 0012 trace 1 ( 2) 0014 putobject 10 0016 setlocal_OP__WC__0 2 # p (-1).abs 0018 trace 1 ( 3) 0020 putself 0021 putobject -1 0023 opt_send_without_block <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0026 opt_send_without_block <callinfo!mid:abs, argc:0, ARGS_SIMPLE>, <callcache> 0029 leave ~~~ putobject -1 の行次にある abs, p (いずれも opt_send_without_block で始まる行) の順序を見ると、 * 最初の実行では ー1 に abs が適用され、次に p が適用されている * 2回目の実行では -1 に p が適用され、次に abs が適用されている となっていますので、これが表示に違いとして出てくるのではないでしょうか。 なお、確かに動作が変わるのですが、私見では * 同一スコープに同じ名前のメソッドとローカル変数がある * メソッド(p) の呼び出しで、括弧を省略している 場合の動作なので、文法というレベルではなく実装依存のレベルのように思います。 適用順を明示的に指定するのであれば、括弧をつければ良いだけですし、同一スコープで 同じ名前を使用するのは勧められない記述だと思うので。 市田 2017年9月5日 21:55 Tadashi Saito <tad.a.digger@gmail.com>: > 斎藤と申します。おもしろい問題ですね。 > > 個人的にはなんとなく既視感があるのですが、過去のメール・チケットの > 中からは、自分はうまく見つけられませんでした。 > > Konishiさんが先に投稿されたことで大方カバーされていると思いますが、 > 自分が調べた点を一つ。 > >> ちなみに、ruby 2.4.1p111での動作です。 > > > 手元で試した限り、同名の変数の有無によって振る舞いが変わるのは、 > 1.8.7〜2.4の全ての系列で同じでした。もっと古いRubyについては、 > まだ試していません。 > > ruby 1.8.7 (2012-06-29 patchlevel 370) [x86_64-linux] > ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-linux] > ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-linux] > ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux] > ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-linux] > ruby 2.3.4p301 (2017-03-30 revision 58214) [x86_64-linux] > ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux] > > (ちなみに、pが引数をそのまま返り値として返すようになるのは1.9から > で、1.8.7までは nil が返ります。そのため、1.8.7の実行では (p(-1.3)).abs > に 対しては nil.abs が実行され、その結果エラーになりました。) > > 以上のように、伝統的な振る舞いである(うっかり変えると悲劇が起きそうな) > のは分かったのですが、これがバグなのか・そうでないのか、JIS/ISO規格の > どこに書いてあるのか・未定義なのか・はたまた規格違反な振る舞いのか、 > あたりは、自分には判断が付きませんでした。 > > もし詳しい方が答えてくだされば、自分としてはうれしいです。 > -- > 斎藤 匡