先日、Junichi Itoさんのこちらの記事を見ていて、safe navigation operator(lonely operator: ぼっち演算子)という言葉に出会いました。気になって調べてみるとなかなか実戦でも使えそうな面白いヤツだったので、少し紹介したいと思います。
Contents
ぼっち演算子とは
ぼっち演算子&.
は、rubyコードにおいてnilを扱いやすくしようという考え方のもと実装された演算子です。
これは object が nil でないときにメソッド foo を呼び出します。
NEWS for Ruby 2.3.0 (Ruby 3.1 リファレンスマニュアル)
実際にどのような挙動をするのか、サンプルコードを書いて試してみます。
ぼっちサンプル
「引数に与えた名前にあいさつを返す」メソッドを持つGreetingクラスを利用することを考えます。素朴には、以下のような実装になるかと思います。
class Greeting def sayHello(name) puts "Hello, #{name}." endendobj = Greeting.newobj.sayHello("Taro")### **Hello, Taro.**
このとき、objがnilであると当然、NoMethodError
が発生します。
class Greeting def sayHello(name) puts "Hello, #{name}." endendobj = nilobj.sayHello("Taro")### undefined method `sayHello' for nil:NilClass (NoMethodError)
では、「nilを含んだ配列」があり、Greetingクラスのオブジェクトである場合だけsayHelloを実行したい、という時にはどういった実装になるでしょうか。実践的なrailsの文脈で言い換えると、「nilが含まれるDBカラムの値を1行ずつ参照して、nilでない場合だけ処理を実行したい」ような時にどういう実装をするでしょうか。
私自身は以下のように書いていました。
class Greeting def sayHello(name) puts "Hello, #{name}." endendobjs = [nil, Greeting.new]objs.each do |obj| unless obj.nil? obj.sayHello("Taro") endend
この実装でも、nilの時はsayHelloの実行を避けることはできています。が、ここでぼっち演算子を使うことで、実装行数をさらに縮約できます。
class Greeting def sayHello(name) puts "Hello, #{name}." endendobjs = [nil, Greeting.new]objs.each do |obj| obj&.sayHello("Taro")end
このlonely operatorを使ったobj&.sayHello("Taro")
の1行だけで、上と同等の処理を行うことができます。NoMethodErrorも発生しません。
ぼっち演算子なら、先に述べたようにrailsで「nilが含まれるDBカラムの値を1行ずつ参照して、nilでない場合だけ処理を実行したい」ような時にコード行数をぐっと減らせそうです。