Procs و Lambdas

تعديل
نسخ الدرس
تحميل الدرس

Procs و Lambdas

في الدرس السابق تعلمنا كيف نستخدم yield لتنفيذ الكتل المُمرَّرة للدوال. لكن ماذا لو أردنا تخزين كتلة برمجية واستخدامها لاحقاً؟ هنا تأتي Procs و Lambdas!

ما هو Proc؟

Proc هو كائن يُمثّل كتلة برمجية. بمعنى آخر، هو طريقة لتخزين كتلة في متغير!

طرق إنشاء Proc

طرق استدعاء Proc

ما هو Lambda؟

Lambda هو نوع خاص من Proc مع قواعد أكثر صرامة. يتصرف بشكل أقرب للدوال العادية.

Lambda مع معاملات

الفرق بين Proc و Lambda

هناك فرقان رئيسيان:

1. فحص عدد المعاملات

Lambda تتحقق من عدد المعاملات بصرامة:

2. سلوك return

هذا الفرق مهم جداً:

الفرق:

  • return في Proc يُنهي الدالة المُحيطة
  • return في Lambda يُنهي Lambda فقط

جدول المقارنة

الميزةProcLambda
فحص المعاملاتمتساهل (يقبل أي عدد)صارم (يجب تطابق العدد)
سلوك returnيُنهي الدالة المُحيطةيُنهي Lambda فقط
الإنشاءProc.new { } أو proc { }lambda { } أو -> { }
التحقق من النوعobj.lambda? يُرجع falseobj.lambda? يُرجع true

تحويل الكتل إلى Procs

استخدام & في تعريف الدالة

استخدام & عند الاستدعاء

اختصار الرموز

تخزين Procs وإعادة استخدامها

إحدى أهم فوائد Procs: يمكن تخزينها وتمريرها!

تخزين في Hash

Closures: الإغلاق

Procs و Lambdas تحتفظ بالسياق الذي أُنشئت فيه:

مثال: عداد

أمثلة عملية

مثال 1: نظام أحداث بسيط

مثال 2: تصفية مخصصة

مثال 3: حساب مرن

متى تستخدم أيهما؟

الحالةالاختيارالسبب
كتلة بسيطة تُمرر لدالةالكتلة العادية { }أبسط وأوضح
تخزين كتلة لاستخدامها لاحقاًProc أو Lambdaكلاهما يعمل
تحتاج سلوك مشابه للدالةLambdaفحص صارم للمعاملات
تحتاج مرونة في المعاملاتProcيقبل أي عدد
return يجب أن يُنهي الدالة المُحيطةProcسلوك return الخاص
return يجب أن يُنهي الكتلة فقطLambdaسلوك return العادي

القاعدة العامة

استخدم Lambda في معظم الحالات لأنها أكثر أماناً وتتصرف كالدوال العادية.

أخطاء شائعة

1. نسيان call

2. خلط return

3. نسيان عدد المعاملات مع Lambda

جدول ملخص

المفهومالصياغةمثال
إنشاء ProcProc.new { }p = Proc.new { puts "!" }
إنشاء Proc (اختصار)proc { }p = proc { puts "!" }
إنشاء Lambdalambda { }l = lambda { puts "!" }
إنشاء Lambda (سهم)-> { }l = -> { puts "!" }
Lambda مع معاملات->(x) { }l = ->(n) { n * 2 }
استدعاء.call()p.call(5)
تحويل كتلة لـ Proc&blockdef foo(&block)
تحويل Proc لكتلة&procarr.map(&my_proc)
فحص النوع.lambda?obj.lambda?

تمرين: Procs و Lambdas

حان وقت التطبيق! في محرر الشيفرة على اليسار:

المطلوب:

  1. أنشئ Lambda اسمه square يُربّع الرقم (n ** 2)
  2. أنشئ Proc اسمه greet يطبع تحية باسم الشخص
  3. استخدم square مع map لتربيع أرقام [1, 2, 3, 4, 5]
  4. استدعِ greet مع اسم "روبي"

الناتج المتوقع:

تلميحات:

  • Lambda: square = ->(n) { n ** 2 }
  • Proc: greet = Proc.new { |name| puts "مرحباً #{name}!" }
  • استخدم &square لتمرير Lambda لـ map
  • استخدم greet.call("روبي") لاستدعاء Proc

تذكّر: Procs و Lambdas تُحوّل الكتل إلى كائنات يمكن تخزينها وتمريرها. Lambda أكثر صرامة وأماناً، بينما Proc أكثر مرونة!