学生からメールが来ました.
研究で作成しているRubyスクリプトが,うまく動かないというのです.
明日じっくり読んで返信しますと,短いメールを送り,次の日にじっくり読んだところ,10分ほどで原因が分かりました.エラーを含む何行かのコードが,1文で表せることにも気づいて,詳しく書いたメールを送りました.
エラーの原因は,値が代入されていない変数を参照した,というやつです.確認コードを:
#!/usr/bin/env ruby a = 0 for i in 1...10 a = i # 外の変数aの値を変える b = i * 2 # ここで最初にbに代入されるとき,bの有効範囲はブロック内 end puts a # 「9」を出力 puts b # bが参照できないのでエラー
ふだん自分はRubyでfor文*1を書くことはほとんどありませんが,学生のバグを再現しようと思い,使ってみました.
実行すると…あれれ,エラーが出ません.「9」と「18」が出力されました.
上記のコメントの「ここで最初にbに代入されるとき,bの有効範囲はブロック内」が間違いなのでした.for文は,endで終わりますが,ブロックを構成しません.http://miyamae.github.io/rubydoc-ja/2.4.0/#!/doc/spec=2fcontrol.html?forにも,「do ... endまたは{ }による ブロックは新しいローカル変数の有効範囲を導入するのに対し、 for文はローカル変数のスコープに影響を及ぼさない」と書いてありました.
エラーを発生させるには,次のようにしないといけません.
#!/usr/bin/env ruby a = 0 10.times do |i| a = i # 外の変数aの値を変える b = i * 2 # ここで最初にbに代入されるとき,bの有効範囲はブロック内 end puts a # 「9」を出力 puts b # bが参照できないのでエラー
実行すると,「undefined local variable or method `b' for main:Object (NameError)」というエラーメッセージが出ました.