0

アプリケーションで使用する単純なイベント バスを作成しています。この部分はうまくいきます:

#!/usr/bin/env ruby

module EventBus
  @callbacks = {}

  module_function

  def on event, &callback
    @callbacks[event] ||= []
    @callbacks[event].push callback
  end

  def fire event, *data
    @callbacks[event].each do |callback|
      callback.call *data
    end
  end
end

EventBus.on :foo do |x| puts x end
EventBus.fire :foo, "test"
# => test

私のプログラムの複雑な性質と、Procs が非常に緩いグースな方法で引数を取るという事実のために、イベントの引数チェックが必要です。lambdaこれに対する明らかな選択は次のとおりです。

EventBus.on :bar, &(lambda do |x| puts x end)

# Will raise an ArgumentError, since the event was fired without any arguments
# Remember that this is the desired behavior
EventBus.fire :bar

明らかに、on呼び出しの構文は&(lambda do ... end). 私はむしろそれを使用してdo ... end(つまり、単項アンパサンド演算子なしで通常のブロックを渡すだけで)、それをラムダに変換できるようにしたいと考えています。私は明白なことを試しました:

...
  def on_lambda event, &callback
    @callbacks[event] ||= []
    @callbacks[event].push(lambda &callback)
    # check if the added callback is lambda. (spoiler alert: it isn't)
    puts @callbacks[event].last.lambda?
  end
end

EventBus.on_lambda :baz do |x| puts x end
# I would expect the callback to be a lambda, and thus throw an ArgumentError,
# but neither of these holds.
EventBus.fire :baz

私が理解しているように、ブロックを取り、それを(を介して)ローカルに参照されるon_lambdaものに変換します。呼び出しの結果を変換してブロックに戻しています。私はこれが から派生したラムダを返すことを期待しているので、私の質問は、なぜ配列の要素が通常の なのかということです。?Proccallback&lambdacallbackcallback ProcProc

ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]


更新: megasの言及に促され{ }て、構文を調べました->() { }(「stab」演算子と呼ばれているのを見ました)。指定されたブロックからラムダを生成します。おそらく、通常のブロック構文と私が望んでいた引数チェックの混合物に近づくのと同じくらい近いでしょう。私がしなければならないのは、onメソッドを微調整することだけです:

def on event, callback
  @callbacks[event] ||= []
  @callbacks[event].push callback
end

次に、コールバックを次のようにアタッチします。

EventBus.on :bam, ->(x) do
  puts x
end

ただし、元の質問についてはまだ興味があります。

4

2 に答える 2

2

これを読むことをお勧めします: http://ruby-doc.org/core-1.9.3/Proc.html#method-i-lambda-3F

于 2012-07-25T20:57:19.100 に答える
1

メソッド呼び出しに渡されるブロックは、常にProcsとしてパッケージ化されます。ラムダが必要な場合は、ラムダ{| ... |と言って、ラムダを明示的に構築する必要があります。...}。ところで。私もprocsよりラムダが好きですが、よく覚えていれば、Matzは彼のチュートリアルでprocsをラムダよりも「より機能的」であると紹介しています(procは可変数の引数などに適応する「トリック」を持っていますが、ラムダはそうではありません)。

ラムダを渡すには、次のようなことを行う必要があります。

def on_lambda event, callback
  (@callbacks[event] ||=[]) << callback
  puts @callbacks[event].last.lambda?
end

EventBus.on_lambda :baz, lambda do |x| puts x end
EventBus.fire :baz
于 2012-07-25T20:17:38.260 に答える