【一人 bugs.ruby Advent Calendar 2020】[Feature #17330] Object#non【11日目】

一人 bugs.ruby Advent Calendar 2020 11日目の記事になります。

[Feature #17330] Object#non

以下のように実装された Object#non メソッドを新しく追加する提案です。

class Object
  # ブロックの戻り値が偽ならレシーバを返し、そうでないなら nil を返す
  def non
    self unless yield(self)
  end
end

この Object#non は以下のような挙動になります。

# 0 じゃない場合はレシーバを返す
p 1.non { _1.zero? }   # => 1
p 0.non { _1.zero? }   # => nil

# 空じゃない場合はレシーバを返す
p [1, 2, 3].non { _1.empty? }  # => [1, 2, 3]
p [].non { _1.empty? }         # => nil

じゃあ、この Object#non って何に使うのかっていうのがチケットにいくつか書かれているので紹介します。

limit = calculate.some.limit
# limit が 0 の場合は DEFAULT_LIMIT を返し、そうでない場合は limit を返す
limit.zero? ? DEFAULT_LIMIT : limit

# もしくは nonzero? メソッドを使う
# これは 0 であれば nil を返し、そうでなければレシーバを返す
calculate.some.limit.nonzero? || DEFAULT_LIMIT
# #non を使うとこんな感じ
calculate.some.limit.non(&:zero?) || DEFAULT_LIMIT
# ^ Note here, how, unlike `nonzero?`, we see predicate-y ?, but it is INSIDE the `non()` and less confusing
# params[:name] があり空でない場合は name に代入する
name = params[:name] if params[:name] && !params[:name].empty?
# ActiveSupport だと presence が使える
name = params[:name].presence
# #non を使うとこんな感じ
name = params[:name]&.non(&:empty?)

こんな感じで #non を使うと ActiveSupport#presence みたいな事ができます。
これは普通に便利そうなので標準にほしいですねえ。