アプリケーションで使用する単純なイベント バスを作成しています。この部分はうまくいきます:
#!/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
私のプログラムの複雑な性質と、Proc
s が非常に緩いグースな方法で引数を取るという事実のために、イベントの引数チェックが必要です。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
ものに変換します。呼び出しの結果を変換してブロックに戻しています。私はこれが から派生したラムダを返すことを期待しているので、私の質問は、なぜ配列の要素が通常の なのかということです。?Proc
callback
&
lambda
callback
callback
Proc
Proc
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
ただし、元の質問についてはまだ興味があります。