2011年4月4日月曜日

rubyのローカル変数とブロックローカル変数の注意点

ローカル変数とブロックローカル変数に、同一の名前をつけた場合の動きのまとめ。

  1. ローカル変数をブロック内で参照できる。
  2. ローカル変数と同名の変数を宣言するには、ブロックパラメータのリストに宣言する。
  3. ローカル変数と同名の変数をブロック変数に使用した場合、ブロックローカルな新しい変数となる。

ローカル変数をブロック内で参照した場合

#coding:utf-8

array = ["h", "o", "g", "e"]
hoge = ""

array.each do |s|
  hoge += s
end
puts hoge

実行結果

ローカル変数がブロック内で参照でき、値が代入されていることがわかる。
hoge

パラメータリストで変数の宣言

#coding:utf-8

array = ["h", "o", "g", "e"]
hoge = "hoge"

array.each do |s;hoge|
  hoge = s
  puts hoge
end
puts "original hoge = [#{hoge}]"

実行結果

ローカル変数が上書きされていないことがわかる。
h
o
g
e
original hoge = [hoge]

ローカル変数と同名の変数を、ブロックパラメータで指定した場合

#coding:utf-8

array = ["h", "o", "g", "e"]
hoge = "hoge"

array.each do |hoge|
end
puts hoge

実行結果

ローカル変数が上書きされていないことがわかる。
hoge
実行時に『-w』を指定して実行すると、ブロックパラメータで同名の変数を使用した場合にワーニングを出すことができる。
実行結果はこんな感じになる。
test.rb:6: warning: shadowing outer local variable - hoge
hoge

javaしかやってないと、なんとなく分かりづらい動きをするもんだなと思ってしまう。
個人的には、この辺の仕様を覚えておくのは大事だと思うけど、同じ名前の変数使わなければいいんじゃねと思ってしまう。
変数使い回すのすきじゃないし・・・。