基本的なスコープの違いを正しく理解できていませんでした。
以下にまとめました。
スコープを作らないグループ(for, while)
for
ループ構文の内外でスコープは変わらない。
forで渡す式はブロックではない
for i in [1, 2, 3] do
num = i
end
puts num
3
forではdo
は省略可能
for i in [1, 2, 3]
num = i
end
puts num
3
forではループ変数もスコープが変わらない
ループ変数i
をforの外でも参照できる
for i in [1, 2, 3]
end
puts i
3
while
whileで渡す式はブロックではない
a = [1, 2, 3]
counter = 0
while counter < a.size do
num = a[counter]
counter += 1
end
puts num
3
whileでもdo
は省略可能
a = [1, 2, 3]
counter = 0
while counter < a.size
num = a[counter]
counter += 1
end
puts num
3
スコープを作るグループ(each, loop)
eachメソッド
以下の例ではArrayクラスのeachメソッドである。Class: Array (Ruby 2_4_0)
ブロックの内外でスコープが変わる。
eachはもちろんdo
必須
[1, 2, 3].each do |i|
num = i
end
puts num
each.rb:5:in `<main>': undefined local variable or method `num' for main:Object (NameError)
loopメソッド
Kernelモジュールのloopメソッドである。Module: Kernel (Ruby 2_4_0)
ブロックの内外でスコープが変わる。
loopでもdo
必須
a = [1, 2, 3]
counter = 0
loop do
break if counter == a.size
num = a[counter]
counter += 1
end
puts num
loop.rb:9:in `<main>': undefined local variable or method `num' for main:Object (NameError)
loopでdo
を省略すると、構文エラーで怒られる
a = [1, 2, 3]
counter = 0
loop
break if counter == a.size
num = a[counter]
counter += 1
end
puts num
loop.rb:7: syntax error, unexpected keyword_end, expecting end-of-input
まとめ
for, whileではループ構文の内外で変数のスコープは変わらない
each, loopではブロックの内外で変数のスコープが変わる
参考リンク
るりま
http://docs.ruby-lang.org/ja/2.1.0/doc/spec=2fcontrol.html#for
制御構造 > 繰り返し > for
for i in [1, 2, 3]
print i*2, "\n"
end
for lhs ... in 式 [do]
式..
end
式を評価した結果のオブジェクトの各要素に対して本体を繰り返して実行します。これは以下の式とほぼ等価です。
(式).each `{' `|' lhs..`|' 式.. `}'
「ほぼ」というのは、do ... endまたは{ }によるブロックは新しいローカル変数の有効範囲を導入するのに対し、for文はローカル変数のスコープに影響を及ぼさない点が異なるからです。
for は、in に指定したオブジェクトの each メソッドの戻り値を返します。
パーフェクトRuby(p.80 3-2-2繰り返し)
for name in %w(Alice Bob Carol)
puts name # 配列の要素が順番に出力される
end
# ループの中で定義された変数を参照できる
puts name # "Carol" と表示
each では繰り返しをブロックで記述していましたが、for に渡す式はブロックではありません。
**ループの内外で変数のスコープは変わらないため、**for の中で使用している変数 name は for の外から参照できます。
その他
[Ruby勉強会@札幌-22に参加しました]
(http://terakonya.sarm.net/wordpress/2012/02/13/rubysapporo-22/)
※「初めてのRuby読み合わせ 6.3.5 for式」の部分
eachはブロック内で定義した変数のスコープはブロック内だけだけど、forの場合はブロックの外側でも変数を参照できる。