Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rubyのぼっち演算子はRailsの`Object#try`より高速(翻訳)

概要

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

Rubyのぼっち演算子はRailsのObject#tryより高速(翻訳)

&.というsafe navigation演算子(Null条件演算子: Rubyでは「ぼっち演算子」とも呼ばれます)はRuby 2.3で導入されました。この演算子は、nilオブジェクトに対してメソッドが呼び出されたときにnilを返します。この演算子がなかったときは、nilオブジェクトに対して呼び出しを行うと以下のようにエラーになりました。

nil.some_method
#=> NoMethodError: undefined method 'some_method' for nil:NilClass

safe navigationが必要な理由

入力値が正しくない場合にオブジェクトを取得できないことは非常によくあります。このような場合、オブジェクトが取れることを期待してメソッド呼び出しを続行すると、オブジェクトがnilの場合に動かなくなるかもしれません。

safe navigationはこうした状況を避けるために導入されました。これを用いて、呼び出すオブジェクトがnilであってもコードが動き続けるようにできます。safe navigationは、メソッド呼び出しが失敗したときにnilオブジェクトを受け取ってもよい場合に使うべきです。

ActiveSupportのtry

RailsではActiveSupport#tryメソッドが利用でき、上述のsafe navigationと似ています。メソッド名からわかるように、#tryはそのオブジェクトが利用可能な場合にメソッド呼び出しを試みます。nilオブジェクトに対してメソッド呼び出しが行われようとすると、エラーではなくnilを返します。

nil.try(:some_method)
#=> nil

Ruby 2.3のsafe navigation

オブジェクトがnilかどうかわからない場合は、たとえば以下のようにメソッド呼び出しの前にアンパサンド&を追加するだけで使えます。

nil&.some_method
#=> nil

上のコードは例外をスローせずにnilを返します。
このコードは次のコードと同等です。

nil ? nil.some_method : nil

つまりオブジェクトがtrueと評価されればオブジェクトに対してメソッドを呼び出し、falseと評価されればnilを返します。

#tryとsafe navigationのどっちを使うか

Railsで仕事をすることが多い人は#tryを常用していることでしょう。#tryとsafe navigation演算子&.パフォーマンスを比較してみると、Rubyでサポートされているsafe navigation演算子の方が遥かに高速で、しかもActiveSupportなどRailsの機能に依存しません。

関連記事

RailsのObject#tryがダメな理由と効果的な代替手段(翻訳)

Ruby: ぼっち演算子`&.`の落とし穴(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。