32

私は一時変数を避け、より流動的なコーディングスタイルを使用できる条件付きの過剰使用を回避しようとする段階を経ています。返品する必要のある価値を手に入れたい場所で使用するのがとても好き#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

明らかに上記の例は単純ですが、それでもこれはルビーコミュニティではかなり一般的なコーディングスタイルです。#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

ここで他にどのようなパターンに従うことができますか。これはすべて一部の人にとっては無意味な砂糖であり、もっと興味深い問題に移るべきだと思いますが、もっと機能的なスタイルで書くことを学ぼうとしているので、長期的なルビイストが何を決定したのか興味がありますこのような状況に取り組む良い方法であるために。これらの例は非常に単純化されています。

4

5 に答える 5

15

定義Object#as

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
于 2011-10-24T16:54:59.207 に答える
12
def best_nice_method
  something_complex(a, b, c).tap |obj|
    break obj.one_more_method_call if a_predicate_check?
  end
end

魔法は別の値breaktap返します。

新着

ルビー2.5はyield_selfまさにあなたが望むものを持っています。 https://stackoverflow.com/a/47890832/683157

于 2017-11-01T02:29:26.360 に答える
6

instance_evalこの目的のために誤用される可能性があります

"this".instance_eval { |test| test + " works" }

2.5以降使用可能yield_self

"easy".yield_self{ |a| a + " peasy" }

続きを読む:

https://ruby-doc.org/core-1.9.3/BasicObject.html#method-i-instance_eval

https://ruby-doc.org/core-2.5.0/Object.html#method-i-yield_self

于 2018-09-06T21:26:45.497 に答える
3

私はあなたが探していたかもしれないファセットgemのメソッドを見つけました:Kernel#ergo

だからあなたの元の方法:

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

次のように表示される可能性があります。

require 'facets/kernel/ergo'

def nice_method
  something_complex(a, b, c).ergo do |_| 
    a_predicate_check? ? _.one_more_method_call : _
  end
end
于 2013-01-17T01:59:04.390 に答える
1

私はこのようなことをする必要があり、トークランドの答えが好きですが、私が書いていた小さなスクリプトのためにオブジェクトを汚染したくありませんでした。代わりに、私はtap配列を利用しました:

[something_complicated].tap { |s| s[0] = new_cool_thing)}.first
于 2015-11-05T00:17:30.323 に答える