Kernel.lambda() لا يقوم بإرجاع lambda Proc في Ruby 1.9
-
11-12-2019 - |
سؤال
أنا أكتب ناقل حدث بسيط لاستخدامه في التطبيق.هذا الجزء يعمل بشكل جيد:
#!/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