2011-08-07 27 views
6

ruby​​ 1.9.2p180(2011-02-18 revision 30909)[x86_64-linux]を実行しています。はなぜ定義されていないのですか?

#!/usr/bin/env ruby 

    def ouch() 
      raise ArgumentError, "woof" 
      fred = 3 
      return(nil) 

    ensure 
      if (defined?(fred)) then 
        printf("fred is defined (%s)\n", fred.inspect()) 
      else 
        printf("fred is not defined\n") 
      end 

    end # ouch() 


    ouch() 

実行すると、上記のルビスクリプトの出力はまったく予想外です。

$ ./ouch.rb 
    fred is defined (nil) 
    ./ouch.rb:4:in `ouch': woof (ArgumentError) 
      from ./ouch.rb:22:in `<main>' 

ので昇給/例外が発生しているが、フレッドは、それによって定義された のためのテストを破って、それが定義され、nilに設定しつつある3に設定されますが、 取得されていません?()。これは非常に混乱しています。これはバグですか?明らかに定義されたテスト の後に、nilでないことのテストが続く必要があります。

これはバグではない場合、なぜ誰かが説明できないのですか?

答えて

7

Rubyのローカル変数は、それらが最初に使用された行と現在のレキシカルスコープの終わりの間で定義されます。暗黙的にnilに初期化されます。

また、この例で考えてみましょう:

if false 
    var = 123 
end 
p var # => nil 

この動作は意図しています。 Rubyは、の構文解析のステップでメソッド呼び出しとローカル変数アクセスを区別できるように設計されています。実行するものではありません。したがって、変数が定義された後は、明示的に値が設定されているかどうかにかかわらず、その名前へのすべての参照が変数にアクセスします。

(誰かがRubyでCALL_VCALLメソッド呼び出しの種類に私を指すようになります場合は、私は私の知る限り、それは唯一のevalで使用されていることをお答えします:あなたがeval -ingているとき、あなたは最初から知っていることはできませんいくつかの変数はIRBの前の行に定義されている場合、それゆえ、このようなアクセスはcatchedしなければならないし、それに応じて派遣。)

+0

Rubyの変数は、それらが最初に割り当てられているソースコードの行から定義されています。割り当てられる前に使用することはできません。だから彼らは "使われているブロックの先頭に定義されていません"。 –

+0

@RobertKlemme優れた点が固定されています。 – whitequark

4
  • バグ
  • ローカル変数は代入によって作成されるわけではありませんが、それが唯一の割り当てことが判明実際には実行されないで、解析する必要があります。
ここ

簡単な例である:

if false 
    alocal = 123 
end 
p defined? alocal 
=> "local-variable" 
関連する問題