Code Fix

初級

配列の範囲外アクセスはエラーにならず nil を返す

存在しない添字で配列にアクセスしても、Rubyはエラーを出さずnilを返すだけです。その後nilに対してメソッドを呼び出すと、そこで初めてNoMethodErrorになります。

なぜエラーが出ないのか

出力: nil
(エラーなし)
Rubyは何も報告しません。文法として正しいためです
出力: nil
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  nums = [1, 2, 3]
 2  puts nums[10].inspect
               ^
出力: nil

存在しない添字にアクセスしても例外にはならず、Rubyは黙ってnilを返します。

直し方: 10 を 1 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  fruits = ["apple", "banana"]
 2  puts fruits[5].inspect
                ^
出力: nil

配列の要素数を超えた添字を指定しても、エラーにならず結果はnilになります。

直し方: 5 を 1 にします。

この問題を解いてみる →

パターン3

 1  scores = [70, 80, 90]
 2  puts scores[100].inspect
                 ^
出力: nil

範囲外アクセスで即座に例外が飛ぶ言語の感覚のままだと、このnilの静かな発生に気づけません。

直し方: 100 を 2 にします。

この問題を解いてみる →

パターン4

 1  names = ["A", "B", "C"]
 2  puts names[9].inspect
               ^
出力: nil

添字が範囲内かどうかは、配列の要素数(length)と照らし合わせて確認する必要があります。

直し方: 9 を 0 にします。

この問題を解いてみる →

パターン5

 1  data = [1, 2]
 2  puts data[7 ].inspect
               ^
出力: nil

このnilが後続の計算に紛れ込むと、ずっと後の行で初めてNoMethodErrorとして表面化します。

直し方: 7 を 0 にします。

この問題を解いてみる →

よくある誤解

「範囲外にアクセスすればすぐ例外で止まるはず」という他言語の感覚は通用しません。Rubyの配列アクセスは範囲外でも黙ってnilを返すため、エラーが起きるのはずっと後の行になることがあります。

実務での勘所

範囲外は常にnilというわけではありません。単独の添字(arr[10])は範囲外なら常にnilですが、開始位置と長さで指定するarr[start, len]や範囲で指定するarr[range]は、開始位置がちょうど配列の要素数と同じであれば、範囲外一歩手前の「境界」とみなされ空配列[]を返します。開始位置が要素数を超えて離れている場合は、単独の添字と同じくnilになります。同じ「範囲外」でも、指定方法と開始位置の関係によってnilになるか空配列になるかが変わる、実務でハマりやすい仕様です。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)