トップレベル,クラス(モジュール)定義,メソッド定義のそれぞれで 独立したスコープになっています.ブロック内では,新たなスコープが 導入されるとともに,外側のローカル変数を参照できます.
ブロック内が特別になっているのは,Thread
や手続きオブジェクトの
中で局所化するためです.
while
,until
,for
は制御構造であり,新しいスコープを
導入しません.
loop
はメソッドで,後ろについているのはブロックです.
Ruby
スクリプトは,Ruby
インタプリタに実行させようとすると,
まず最後まで一度読みこまれ,構文解析されます.構文上問題が生じなければ,
構文解析で作られた構文木が最初から実行に移されます.
ローカル変数が参照可能になるのは,この構文解析の時にローカル変数への 代入文が見つかった時です.
for i in 1..2
if i == 2
print a
else
a = 1
end
end
test.rb
というファイルにいれて,このスクリプトを実行すると,
test.rb:3: undefined local variable or method `a' for
#<Object:0x40101f4c> (NameError)
from test.rb:1:in `each'
from test.rb:1
ということで,i
が1の時は,エラーが起こらず,i
が2になった時に
エラーが起こります.構文解析の時には,最初のprint a
が実際には
a
への代入が行われてから実行されるというところまで解析されず,
この文を構文解析する時までにa
への代入文が現われていないので,
ローカル変数は参照されません.実行時にはa
というメソッドが
ないか探しますが,これも定義されていないのでエラーになります.
逆に,次のスクリプトは,エラーになりません.
a = 1 if false; print a
# ->nil
ローカル変数のこのような振舞いに悩まされないためには,ローカル変数が
参照される文より前に,a = nil
といった代入文を置くことがすすめられて
います.こうすると,ローカル変数の参照が速くなるというおまけもついて
います.
クラス/モジュールで定義された定数は,そのクラス/モジュールの中で 参照できます.
クラス/モジュール定義がネストしている場合には,内側のクラス/モジュール から外側の定数を参照できます.
またスーパークラス及びインクルードしたモジュールの定数を参照できます.
トップレベルで定義された定数は,Object
クラスに追加されますので,
すべてのクラス/モジュールから参照できます.
直接参照できない定数は,::
演算子を使って,クラス/モジュール名を
指定することにより参照できます.
次のような例でしょうか.
A = a = b = "abc"; b << "d"; print a, " ", A
# ->abcd abcd
変数や定数への代入は,オブジェクトを後でその変数や定数で参照する
ために用いられます.変数や定数にオブジェクトそのものが代入されて
いるのではなく,オブジェクトの参照を保持しているだけです.変数は,
この参照を変更して異なるオブジェクトを参照するようにすることが
できますが,定数では一度保持した参照を変更することができません.
変数や定数にメソッドを適用すると,そのメソッドは,変数や定数が 指しているオブジェクトに適用されます.上の例では,<<というメソッドが オブジェクトの状態を変えてしまうために,「予期せぬ」結果が生まれて います.オブジェクトが数値の場合には,数値の状態を変えるメソッドが ないため,このような問題は生じません.数値にメソッドを適用した時には 新しいオブジェクトが返されます.
この例では,文字列で示しましたが,配列やハッシュなど,オブジェクトの 状態を変更するメソッドを持っているオブジェクトでも同様のことが起こり 得ます.
Fixnum
,true
,nil
,false
が即値だということですが,参照との違いは何ですか特異メソッドを定義できないという制限がある他は,即値と参照の違いは 特にありません.
定数があるオブジェクトを指しているとき,別のオブジェクトを指すように はできませんが,そのオブジェクトが破壊的メソッドを持っていれば, オブジェクトの内容は変更できます.