まつもと ゆきひろです.

In message "[ruby-list:1209] [Q] Scope of local variable"
    on 96/12/08, Shin-ichiro Hara <sinara / blade.nagaokaut.ac.jp> writes:
|
|原です。
|
|どうもループの中の局所変数の扱いが分からなくなってし
|まいました。

まず大原則

  * ローカル変数のバインドは静的に行われています.
  * ローカル変数は最初の代入文で定義されます.

これを適用すると

|------------^ test1.rb
|for i in 0..1
|  print defined?(j), "\n"
|  j = 0
|end
|------------$ test1.rb

|FALSE
|FALSE
|
|と出力されます。これはなぜでしょう?

が理解できると思います.

|------------^ test2.rb
|#j = 0
|for i in 0..2
|  print "1)", defined?(j), "\n"
|  j = -100 if FALSE
|  print "2)", defined?(j), "\n"
|  print "3)", j, "\n"
|  j = j+1
|end
|------------$ test2.rb
|
|の結果は
|
|1)FALSE
|2)local-variable
|3)nil
|1)FALSE
|2)local-variable
|3)1
|1)FALSE
|2)local-variable
|3)2
|
|となります。「j = -100 if FALSE」で j が定義されるのは
|なぜでしょうか?さらに一辺、未定義になっても前回の値を
|記憶しているのも不思議です。最初の行の j = 0 のコメント
|を外せば期待通りの出力ですが。

最初の疑問は

  * 代入という操作で変数が定義される訳ではなく,代入文が現れ
    ることによって(実行されなくても)定義される

という原則で説明されます.変数が定義されている範囲は静的に決
まりますが(最初の代入文からブロックの終わりまで),その範囲で
未定義だからといって変数が無くなる訳ではないです.

つまり

|------------^ test2.rb
|#j = 0
|for i in 0..2
|  print "1)", defined?(j), "\n"
*  j = -100 if FALSE
>  print "2)", defined?(j), "\n"
>  print "3)", j, "\n"
>  j = j+1
>end
|------------$ test2.rb

*の行の代入文によってローカル変数jが定義され,>の範囲内で定
義されています.定義されているとはプログラム中でjという識別
子によってその変数にアクセスできるかどうかをしめすものです.

# これにさらに動的変数が絡むとますますややこしくなるんですけ
# ど,ここでは説明しません.

                                まつもと ゆきひろ /:|)