سؤال

أنا أكتب ناقل حدث بسيط لاستخدامه في التطبيق.هذا الجزء يعمل بشكل جيد:

#!/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إذا كنت تأخذ الحجج بطريقة فضفاضة للغاية، أريد بعض الحجج للتحقق من الأحداث الخاصة بي. 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]


تحديث:مدفوعًا بذكر ميجاس لـ { } نظرت في ->() { } بناء الجملة (لقد رأيته يسمى عامل التشغيل "الطعنة").وتنتج لامدا من الكتلة المحددة.من المحتمل أن يكون هذا أقرب ما يمكنني الوصول إليه من مزيج من بناء جملة الكتلة العادي والتحقق من الوسيطات التي أردتها.كل ما علي فعله هو تعديل on طريقة:

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

ثم قم بإرفاق عمليات الاسترجاعات مثل ذلك:

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

ومع ذلك، ما زلت أشعر بالفضول بشأن السؤال الأصلي.

هل كانت مفيدة؟

المحلول

أود أن أقترح قراءة هذا: http://Ruby-doc.org/core-1.9.3/Proc.html#method-i-lambda-3F

نصائح أخرى

يتم دائمًا تجميع الكتل التي تم تمريرها إلى استدعاءات الطريقة في صورة Procs.إذا كنت تريد Lambdas ، فيجب عليك بنائها بشكل صريح ، بقول Lambda {| ... | ...}.بالمناسبة.أنا أيضًا أحب lambdas أفضل من procs، لكن إذا كنت أتذكر جيدًا، يقدم Matz في برنامجه التعليمي procs على أنها "أكثر تميزًا" من lambdas (procs "لديها حيل" للتكيف مع عدد متغير من الوسائط وما إلى ذلك، لا تمتلك lambdas ذلك).

سيتعين عليك القيام بشيء كهذا لتمرير lambdas:

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top