44294


以下のrubyのコードについて、`result1`は出力できるのに`result2`は出力できないのはなぜですか?

[code]

    if result1 = 'hoge'
      puts "result1 is #{result1}"
    end
    
    puts "result2 is #{result2}" if result2 = 'hoge'
    
[/code]

* * *
[code]

    $ ruby -v
    ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin16]
    $ ruby sample.rb
    sample.rb:1: warning: found = in conditional, should be ==
    sample.rb:5: warning: found = in conditional, should be ==
    result1 is hoge
    Traceback (most recent call last):
    sample.rb:5:in `<main>': undefined local variable or method `result2' for main:Object (NameError)
    Did you mean?  result1
    
[/code]


CC BY-SA 4.0
2018-05-27T06:30:49.260
44291
2018-05-27T08:38:48.153
28630
question
ruby
rubyのinline if のscopeについて


[@metropolis さんが示してくれているリンク](https://ruby-
doc.org/core-2.5.1/doc/syntax/control_expressions_rdoc.html#label-
Modifier+if+and+unless)に、答えは書いてありますが、リンクは回答としてはあまり適切ではないので、まとめてみます。

似たような if 文での処理を見てみると、次のようになっています。

[code]

    result2 = :foo
    puts result2 if result2 = :hoge
    # => hoge
    
    0 if result3 = :fuga
    puts result3
    # => fuga
    
[/code]

結論として言えることは、今回問題になっている undefined local variable は、 if/unless modifier clause
の中で初めて変数を定義し、かつ、その定義される変数を本文において利用していた場合に発生する様子です。

このことの説明は、上記のリンクから辿れますが、説明してみると、 ruby のインタプリタの動作として、 if/unless modifier clause
を処理するときに、

  1. 最初に変数が bind している変数メタデータストアを、(おそらくその1文で変数が表われた順に)特定し
  2. 次に if の中身を評価し
  3. 条件を見たしていることが分かれば本文を実行する

という処理をしている様子です。

問題は、上記のような処理を行った場合、 if/unless modifier clause
付きの文であると、その条件式の中で変数が定義されることになったとしても、最初に本文 result2 の変数出現に対しては変数が存在しないとして 1
のプロセスで処理されてしまっているため、本文が実行される段階になった際には、そんな名前の変数は存在しなかった例外を生成してしまう様子です。

結論から言えるのは、 modifier if clause の中で代入は行わない方が無難だな、と思った次第です。


CC BY-SA 4.0
2018-05-27T08:38:48.153
44294
2018-05-27T08:38:48.153
754
44291
answer