このエントリは拙著「プロを目指す人のためのRuby入門(通称・チェリー本)」のサポート記事です。
プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで Software Design plus
- 作者:伊藤 淳一
- 発売日: 2017/11/25
- メディア: Kindle版
6.3.3項(187〜188ページ)に載っているサンプルコードをirb上で写経していくと、書籍ではエラーになるはずのコードがエラーにならないケースがあります。
これはirb上で連続してコードを打ち込んでいるためです。
一度irbを再起動させてからエラーになるコードを入力すると、書籍の説明通りエラー(NameError)が発生します。
もっとくわしく
6.3.3項のサンプルコードをirb上で打ち込むと、次のコードを実行することになります。
text = '私の誕生日は1977年7月17日です。' # キャプチャの名前がそのままローカル変数に割り当てられる if /(?<year>\d+)年(?<month>\d+)月(?<day>\d+)日/ =~ text puts "#{year}/#{month}/#{day}" #=> 1977/7/17 end
この時点でyear
、month
、day
という3つのローカル変数がirb内に定義されます。
その次に出てくる以下のサンプルコードは、「正規表現を使ってもローカル変数が作成されない」ということを説明するためのコードです。
text = '私の誕生日は1977年7月17日です。' # 正規表現が右辺に来るとローカル変数が作成されない if text =~ /(?<year>\d+)年(?<month>\d+)月(?<day>\d+)日/ puts "#{year}/#{month}/#{day}" end #=> NameError: undefined local variable or method `year' for main:Object
なのですが、1つ前のコードを実行したことにより、すでにyear
、month
、day
がローカル変数として定義されてしまっています。
そのため、本来であれば「year
が未定義なのでエラー(NameError)」となるべきところが、エラーにならず普通に実行できてしまうわけです。
# 本当はyearもmonthもdayもないよ!となるはずが、すでに存在するので動いてしまう puts "#{year}/#{month}/#{day}"
irbを再起動すればローカル変数はすべてクリアされます。
ですので、再起動した直後に先ほどのコードをもう一度実行すれば、期待どおり「year
が未定義なのでエラー(NameError)」になります。
まとめ
この件はフィヨルドブートキャンプの生徒さんやSNS上の読者さんで、同じ疑問を持っていた人を見かけたので、今回ブログ記事として説明させてもらいました。
記述ミスではないとはいえ、初心者さんにとってはたしかにややこしい落とし穴になってしまっているため、改訂版を出す機会があればこの点をひとこと補足しておこうと思います。
プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで Software Design plus
- 作者:伊藤 淳一
- 発売日: 2017/11/25
- メディア: Kindle版