備忘。
今まで知らなかったので、記憶に留めたいので記録しておく。
hoge&.empty?
のように、「&.」をつけたRubyの記法を、最近知りました。
「Safe Navigation Operator」(別名:「ぼっち演算子」)と言って、オブジェクト(この場合「hoge」)がnilでも、例外(NoMethodError)にならずにnilを返してくれるとのこと。
では、実際にそうなるか確認してみます。
まずは、「&.」がない場合。
Hashが空かどうかを判定するために、引数hashに対してempty?を実行するメソッドを用意。
引数に、空Hashもしくは空でないHashを渡せば、メソッド内のempty?は想定通りに動く。
ただし、引数がnilの場合は、nilにempty?メソッドは無いため「NoMethodError」が発生している。
pry(main)> def is_empty(hash) pry(main)* hash.empty? pry(main)* end => :is_empty pry(main)> is_empty({}) => true pry(main)> is_empty({"a" => 1}) => false pry(main)> is_empty(nil) NoMethodError: undefined method `empty?' for nil:NilClass
一方、「&.」がある場合。
同じく、Hashが空かどうかを判定するために、引数hashに対してempty?を実行するメソッドを用意。
ただし、内部のロジックでは「&.」を利用して、nilの時でもエラーにならないように意識している。
引数に、空Hashもしくは空でないHashを渡せば、メソッド内のempty?は、やはり想定通りに動く。
では、引数をnilの場合はどうか。
今回は、hash&.の時点でnilが判定されるため、empty?を実行せずにnilが返ってきている。*1
そのため、NoMethodErrorは発生していません。
pry(main)> def is_empty_safe(hash) pry(main)* hash&.empty? pry(main)* end => :is_empty_safe pry(main)> is_empty_safe({}) => true pry(main)> is_empty_safe({"a" => 1}) => false pry(main)> is_empty_safe(nil) => nil
なお、「&.」の挙動としては、「レシーバーがnilでない場合に、その後に続くメソッドを呼び出す」のだそうです。
比較対象にされる「#try」は「(respond_to? メソッドを利用して)メソッドを呼び出し可能な場合にメソッドを呼び出す」とのこと。
ちなみにこの機能、Ruby2.3から実装されているということ。。。
これを知った時、いかに時代に取り残されていたか*2...と感じてしまった。
とはいえ、知らなかったことを知れただけでも、昨日の自分から一歩前進したということで「ヨシ!」とします。