Ruby 2.6: Rangeに`nil`が入ってないか注意しよう(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Ruby: Rangeにnilが入ってないか注意しよう(翻訳)

Ruby 2.6ではRangeの構文が拡張され、終端に無限の値も使えるようになったことで「エンドレス」を扱えるようになりました。この新しい構文はRubyドキュメント(英語)に記載されています。

この構文は、「ある日付から任意の未来の日付までの期間」などの概念を表現するのに優れていますが、構文に新しいシンタックスシュガーをまぶして変更したことで、既存の振る舞いが変わります。

以前のRubyの場合

rangeにnilを渡すとArgumentErrorになる。

end_of_range = nil
(1..end_of_range).map { |i| do_something(i) }
#=> ArgumentError (bad value for range)

現在のRubyの場合

Rangeの終端のnilはエラーではなくなり、「エンドレス」のrangeを表す。

end_of_range = nil
(1..end_of_range).map { |i| do_something(i) }
#=> infinite loop!

注意が必要な理由

エンドレスのrangeを作成する機能はRuby 2.5以前にもありましたが、Float::INFINITYなどのように明示的な特殊定数を用いる方法だけが利用可能でした。

メソッドの結果が予期せずnilなってしまう可能性の高い言語で、nilがrangeの有効な入力であるとみなされるようになると、見つけにくい誤りの発生場所が確実にまた1つ増えてしまいます。

避けて通れない理由

この構文は言語に組み込まれているので、実際には選択の余地がありません。

しかし、Rangeに渡される値のチェックを励行することで身を守ることは可能です。コードのあちこちにnilチェックをばらまくのは「グッドプラクティス」とみなされていませんが、Rubyがオブジェクト指向プログラミングへのアプローチにおいて純潔であろうとしたことはこれまで一度もありません。

関連記事

Rails: スコープはスコープを返すべき(翻訳)

Rails: コードをシンプルにする2種類の委譲(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ

BPSアドベントカレンダー