6

私はNameError: undefined local variable or methodルビー2.1.2を取得しています

この質問で見られるように、式は次のようになります。

bar if bar = true

は、割り当てられる前にパーサーによって読み取られるため、未定義のローカル変数エラーが発生します (bar事前に定義されていない場合) 。barそして、私はこの表現でそれと違いがなかったと信じています:

bar if bar = false

2 つの違いは、本体が評価されるかどうかですが、未定義のローカル変数に遭遇すると、条件を評価する前にすぐにエラーが発生する場合は問題ありません。

しかし、Ruby 2.1.2 で 2 番目のコードを実行すると、エラーは発生しません。以前からそうでしたか?もしそうなら、解析の議論は何でしたか? そうでない場合、Ruby の仕様は変更されましたか? それへの言及はありますか?1.8.7、1.9.3 などで何をしましたか?

4

3 に答える 3

5

barが定義されているかどうかに違いはありません。どちらの場合も、bar本体では未定義です。ただし、後者の場合、body は評価されないため、問題ありません。name を解決することはないため、名前解決bar中にエラーが発生することはありません。

ローカル変数は、代入が解析されるときに定義されます。これらは代入が実行されると初期化されます。

変数がユニット化されるのはまったく問題ありません。nilその場合、次のように評価されます。

if false
  bar = 42
end

bar
# => nil

ただし、変数がundefinedの場合、Ruby は裸の単語がローカル変数なのか、受信者なしの引数なしのメッセージ送信なのかわかりません。

foo
# NameError: undefined local variable or method `foo'
#                                     ^^^^^^^^^
# Ruby doesn't know whether it's a variable or a message send

と比べて:

foo()
# NoMethodError: undefined method `foo'
# ^^^^^^^^^^^^^

self.foo
# NoMethodError: undefined method `foo'
# ^^^^^^^^^^^^^

すべて一緒に:

foo()
# NoMethodError: undefined method `foo'

self.foo
# NoMethodError: undefined method `foo'

foo
# NameError: undefined local variable or method `foo'

if false
  foo = 42
end

foo
# => nil

foo = :fortytwo

foo
# => :fortytwo

この特定のケースの問題は、式が解析される順序 (したがって、変数が定義される順序)が、式が実行される順序と一致しないことです。

割り当てが最初barに実行されるため、本体で定義されると想定されます。しかし、そうではありません。本体が最初に解析されたため、これがメソッドなのか変数ノードなのか、代入が見られるに構文ツリーに挿入されたのかわからないからです。

ただし、そのノードが解釈されない場合、つまり条件が false の場合は、悪いことは何も起こりません。

于 2014-08-14T11:34:27.303 に答える
1

はい、Ruby 2.1.2 で変更されました

1.8.71.9.3、さらに2.0.02.1.12 つの警告が表示され、エラーは発生しません。

2.0.0-p247 :007 > bar if bar = false
(irb):7: warning: found = in conditional, should be ==
 => nil 
2.0.0-p247 :008 > bar if bar = true
(irb):8: warning: found = in conditional, should be ==
 => true 

2.1.2あなたが言及したバージョンでは、2つの警告と1つのNameErrorエラーが発生します。

2.1.2 :001 > bar if bar = true
(irb):1: warning: found = in conditional, should be ==
NameError: undefined local variable or method `bar' for main:Object
        from (irb):1
        from /home/durrantm/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :002 > bar if bar = false
(irb):2: warning: found = in conditional, should be ==
 => nil 

これは私のUbuntu 14にあります

于 2014-08-14T11:40:46.930 に答える