1.9ではブロック変数はブロックローカル変数として扱われる
つまり、ブロック内のパラメータとして定義された変数のスコープはブロック内に限定される、ということ。これをブロックローカル変数という。
試しに下記のコードを1.8.7、1.9.3それぞれのバージョンで実行してみる。
block_test.rb
x = 1 ary = [1,2,3] ary.each do |x| puts x end p x
1.8.7での実行結果
$ ruby block_test.rb 1 2 3 3
1.9.3での実行結果
$ ruby block_test.rb 1 2 3 1上記のように、1.8.7では最初に定義したx=1がイテレータ実行による影響を受けて x=3 になっているが、1.9.3では x=1 が保持されている。
ブロックパラメータで指定していない変数はブロックローカルにはならない
ブロック内でパラメータとして定義されずに利用された変数はブロックローカルな変数ではないため、ローカル変数として扱われる。
例えば、
x = 1 ary = [1,2,3] ary.each do |y| x = y end p xとすると結果は x=3 になる。念のため。
また、上記のようなケースで x もブロックローカルにするためには下記のように記述する。
x = 1 ary = [1,2,3] ary.each do |y; x| x = y end p x
上記の実行結果は x=1 になる。
<以下、2012/03/05追記>
もうちょっと複雑にしてみると、
x = y = z =0 # 変数初期化 ary = [1, 2, 3] ary.each do |x; y| # 配列の要素はxに順番に代入される。yはブロック内のみをスコープとしたブロックローカル変数 y = x # ブロック変数xに配列の要素が順番に追加され、ブロックローカル変数yに代入される z = x # ブロック変数xに配列の要素が順番に追加され、ローカル変数zに代入される p [x, y, z] end p [x, y, z]
実行結果は下記のようになる。
[1, 1, 1] [2, 2, 2] [3, 3, 3] [0, 0, 3]
ブロックローカル変数として定義をしなかったzのみ影響を受けていることがわかる。
参考サイト
Ruby 1.9に移行する際に注意すべき10のポイント - なんとなく日記
0 件のコメント:
コメントを投稿