4

関数がラムダとして変数に格納されている場合、オブジェクトで関数を呼び出す (メッセージを送信する) ことは可能ですか?

次のような配列があるとします%w(a b c)

次に、次のようなメソッドをチェーンできます。

%w(a b c).reverse.map(&:upcase) # => ["C", "B", "A"] 

変数への連鎖メソッド呼び出しを抽出し、それらを他の配列オブジェクトに適用することは可能ですか?

transform = -> { reverse.map(&:upcase) }

私は次のことを試しましたが、運がありませんでした:

JRuby 1.7.1 の使用

%w(a b c).send(transform)
TypeError: #<Proc:0x19a639d8@(irb):12 (lambda)> is not a string

%w(a b c).send(&transform)
ArgumentError: wrong number of arguments (0 for 1)

Ruby 1.9.3 を使用する

%w(a b c).send(transform)
TypeError: #<Proc:0x007fa0721f0dc8@(irb):1 (lambda)> is not a symbol

%w(a b c).send(&transform)
ArgumentError: no method name given
4

2 に答える 2

8

少なくとも 2 つのアプローチがあります。

1)暗黙のレシーバーでラムダを書くのが好きなようです(私はそれをお勧めしません、self明らかに変更します)、あなたはそのためのinstance_execを持っています:

transform = -> { reverse.map(&:upcase) }
["a", "b", "c"].instance_exec(&transform)
#=> ["C", "B", "A"]

2) カスタム拡張機能を記述します。たとえば、次のようになりObject#applyます。

class Object
  def apply(block, *args)
    block.call(self, *args)
  end
end

transform = -> strings { strings.reverse.map(&:upcase) }
["a", "b", "c"].apply(transform)
#=> ["C", "B", "A"]
于 2012-12-07T19:24:34.207 に答える
0
class Array
  def transform; reverse.map(&:upcase) end
end

%w(a b c).send(:transform)
于 2012-12-07T19:19:05.847 に答える