25

関数fooを定義します。

def foo(s)
  case s
  when'foo'
    x = 3
    puts x.inspect
  when 'bar'
    y = 4
    puts y.inspect
  end
  puts x.inspect
  puts y.inspect
end

次に、それを次のように呼びます。

1.9.3p194 :017 > foo('foo')
in foo scope
3
in outer scope
3
nil
 => nil 

1.9.3p194 :018 > foo('bar')
in bar scope
3
in outer scope
nil
3
 => nil 

どちらの場合でも、関数が未登録のローカル変数に関するエラーをスローしないのはなぜですか?最初のケースでは、変数yは存在してはならないように見えるためinspect、外部スコープで呼び出すことはできません。x2番目の場合も同じです。

別の同様の例を次に示します。

def test1
  x = 5 if false
  puts x.inspect
end

def test2
  puts x.inspect
end

その後:

1.9.3p194 :028 > test1
nil
 => nil 

1.9.3p194 :029 > test2
NameError: undefined local variable or method `x' for main:Object

何が起きてる?Rubyが変数宣言を外部スコープに引き上げているように見えますが、これがRubyが行っていることであることに気づいていませんでした。(「ルビー巻き上げ」を検索すると、JavaScript巻き上げに関する結果のみが表示されます。)

4

2 に答える 2

62

この式のように、Rubyパーサーがシーケンス識別子、等号、値を確認した場合

x = 1

と呼ばれるローカル変数にスペースを割り当てますx。変数の作成(値の割り当てではなく、変数の内部作成)は、コードが実行されていない場合でも、常にこの種の式の結果として行われます。この例を考えてみましょう。

if false
  x = 1
end
p x # Output: nil
p y # Fatal Error: y is unknown

x失敗した条件付きテストにラップされているため、への割り当ては実行されません。しかし、Rubyパーサーはシーケンス x = 1を確認し、そこからプログラムにローカル変数が含まれていると推測しますxxパーサーは、値が割り当てられているかどうかを気にしません。その仕事は、スペースを割り当てる必要があるローカル変数のコードを精査することです。その結果x、奇妙な種類の可変リンボに生息します。になり、に初期化されましたnil。その点で、まったく存在しない変数とは異なります。例でわかるように、調べる xと値が得られますが、 nil存在しない変数を調べようとするとy致命的なエラーが発生します。しかし、x存在しますが、プログラムでは何の役割も果たしていません。これは、解析プロセスのアーティファクトとしてのみ存在します。

しっかりとしたRubyistの第6.1.2章

于 2012-10-17T06:17:28.157 に答える
3

ルビーパーサーはすべての行を通過し、すべてをゼロに設定しますvariable =。実際に実行されているコードかどうかは関係ありません。

実行されなかったif/unless / caseステートメントの外部で変数を参照できるのはなぜですか?を参照してください

于 2012-10-17T06:08:38.113 に答える