Techioz Blog

タップのような組み合わせメソッドですが、別の値を返すことはできますか?

概要

私は、より流動的なコーディング スタイルを使用できるように、一時変数と条件の過度の使用を回避しようとする段階を経ています。私は、返す必要がある値を取得したいが、値を返す前に何らかの処理を行いたい場所で #tap を使用することを非常に気に入っています。

def fluid_method
  something_complicated(a, b, c).tap do |obj|
    obj.update(:x => y)
  end
end

対手順:

def non_fluid_method
  obj = something_complicated(a, b, c)
  obj.update(:x => y)
  obj # <= I don't like this, if it's avoidable
end

明らかに上記の例は単純ですが、それでもこれは Ruby コミュニティでは非常に一般的なコーディング スタイルです。 #inject を使用してオブジェクトを一連のフィルターに渡すこともあります。

things.inject(whatever) do |obj, thing|
  thing.filter(obj)
end

対手順:

obj = whatever
things.each do |thing|
  obj = thing.filter(obj)
end
obj

現在、次のような条件が繰り返し使用されることに直面しており、それを処理するためのより流動的なアプローチを探しています。

def not_nice_method
  obj = something_complex(a, b, c)
  if a_predicate_check?
    obj.one_more_method_call
  else
    obj
  end
end

(少し) よりクリーンな解決策は、重複を犠牲にして一時変数を避けることです。

def not_nice_method
  if a_predicate_check?
    something_complex(a, b, c).one_more_method_call
  else
    something_complex(a, b, c)
  end
end

ここでは #tap に近いものを使いたい気持ちが抑えられませんが。

他にどのようなパターンに従うことができますか。一部の人々にとって、これはすべて無意味な砂糖であることはわかっています。もっと興味深い問題に移るべきだとは思いますが、私はより機能的なスタイルで書くことを学ぼうとしているので、長年の Rubyist が何を判断したかに興味があります。このような状況に対処する良い方法になります。これらの例は大幅に簡略化されています。

解決策

オブジェクト#を次のように定義します。

class Object
  def as
    yield self
  end
end

そして、次のように書くことができるようになりました。

def not_sure_this_is_nice_enough_method1
  something_complex(a, b, c).as do |obj| 
    a_predicate_check? ? obj.one_more_method_call : obj
  end
end