Ruby / العقود: الاستدعاء والتقييم والإخفاق ونماذج القيم / الدرس 7
ضبط أعمار الكتل و Proc و lambda
افهم التقاط الحالة ومعالجة المعاملات والعودة غير المحلية والاستدعاء المتزامن قبل تخزين النداءات وإعادة استخدامها.
في هذه الصفحة
أهداف الدرس
- ميّز سلوك معاملات lambda وعودتها من سلوك Proc العادية.
- حدّد عدد مرات تشغيل النداء ومالك حالته الملتقطة وعمرها.
قد تخفي صياغات الاستدعاء المتشابهة عقودا مختلفة
تُمرر كتلة Ruby مع استدعاء طريقة، بينما تمثل Proc حسابا شبيها بالكتلة في كائن يمكن تخزينه واستدعاؤه. و lambda هي Proc ذات قواعد خاصة للمعاملات والتحكم. تحول & بين معامل كتلة وتمثيل Proc عند الحد. لا تنشئ أي منها خيطا أو مهمة خلفية أو دائمة. قبل قبول النداء حدّد مدخلاته وعدد تشغيله وآثاره واستثناءاته وعمره. تظل closure المريحة سلوكا تطبيقيا يحتاج مالكا مسؤولا.
اختر معالجة المعاملات الصارمة أو المتسامحة عمدا
تفحص lambda معاملاتها عادة كالطريقة، بينما قد تتسامح Proc العادية في نقص المعاملات الموضعية أو زيادتها. قد يحول التسامح النقص إلى nil بدلا من كشف خطأ المستدعي فورا. تضيف الكلمات المفتاحية والتفكيك تفاصيل، فافحص التوقيع الدقيق ولا تقل إن كل كتلة تقبل أي شيء. يعرض المثال معامل lambda واحدا ومعاملي Proc مع قيمة واحدة فقط. المخرج مستنتج من دلالات Ruby 3.3 ولم ينفذه مفسر.
strict = ->(value) { value * 2 }
lenient = proc { |value, extra| [value, extra] }
puts strict.call(3)
p lenient.call(3)
puts strict.lambda?
puts lenient.lambda?
6
[3, nil]
true
false
المخرج المتوقع 6 ثم [3, nil] ثم true ثم false. يؤدي عدد معاملات خاطئ لـ strict إلى الرمي، بخلاف Proc المتسامحة؛ ولا ينفذ المثال الاستدعاء الفاشل.
قد تستهدف return طريقة محيطة
قد تعود return داخل Proc عادية من الطريقة التي أُنشئت فيها، لا من استدعاء النداء فقط. أما return في lambda فمحلية لها. وإذا حاولت Proc عودة غير محلية بعد انتهاء طريقة تعريفها فقد ترمي LocalJumpError. يهم ذلك عند تخزين النداء لاحقا بدلا من تشغيله فورا. لـ next و break سلوك يعتمد على السياق أيضا؛ فلا تعاملهما كعودة طريقة. اجعل حدود النداء واضحة بما يكفي لمعرفة هدف التحكم.
لاحظ موضع استمرار التنفيذ
تختلف الطريقتان بنوع النداء ومعالجة نتيجته. تخرج عودة Proc من الطريقة قبل تعبيرها الأخير، بينما تعيد lambda قيمة تسمح للطريقة ببناء نتيجة أخرى. لا توجد I/O سوى الطباعة ولا حالة خارجية. لا تستنتج ضرورة lambda لكل نداء؛ اختر بروتوكول الواجهة ووثّقه. العودة غير المحلية المفاجئة مشكلة عقد، لا سبب لالتقاط كل استثناء حول المكرر.
def via_proc
callback = proc { return 'method-return' }
callback.call
'after'
end
def via_lambda
callback = -> { return 'lambda-return' }
value = callback.call
"after:#{value}"
end
puts via_proc
puts via_lambda
method-return
after:lambda-return
المخرج المتوقع method-return ثم after:lambda-return. المثال مستقل وغير منفذ، ويشرح التحكم لا جدولة نداء غير متزامن.
للمتغيرات القابلة للتعديل الملتقطة عمر مستمر
قد ترى closure تغير المتغير لاحقا؛ فلا يعني تخزين شرط التقاط قيمة مجمدة وقت الإنشاء. أنشئ لقطة محلية مقصودة عند لزومها. وقد تشترك المصفوفات والنصوص الملتقطة مع مراجع أخرى. يحتاج أمان الخيوط مزامنة أو ملكية، لا غلاف Proc فقط. تختلف أسبقية ربط الأقواس المعقوفة و do/end في بعض التعابير؛ فاستخدم الأقواس أو استدعاء أبسط إذا التبست الطريقة التي تتلقى الكتلة. اختبر الاستدعاء الفوري والمؤجل وفق العقد الفعلي.
الأخطاء الشائعة وإصلاحها
ترمي Proc مخزنة LocalJumpError عند العودة.
- لماذا يحدث؟
- انتهى هدف عودتها غير المحلية بالفعل.
- كيف تصلحه؟
- استخدم lambda محلية العودة أو أعد تصميم عمر النداء.
- كيف تتجنب تكراره؟
- راجع هدف العودة عندما يغادر النداء طريقة تعريفه.
يصبح معامل نداء ناقص nil دون ملاحظة.
- لماذا يحدث؟
- أخفى تسامح Proc الموضعي عدم التطابق.
- كيف تصلحه؟
- استخدم عقد استدعاء صارما أو تحقق من المعاملات.
- كيف تتجنب تكراره؟
- افحص عدد المعاملات والكلمات المفتاحية عند التكامل.
يرى نداء عتبة مختلفة عن اللقطة المتوقعة.
- لماذا يحدث؟
- التقط متغيرا تغيرت قيمته لاحقا.
- كيف تصلحه؟
- التقط قيمة ثابتة مقصودة أو وثّق معنى الحالة الحية.
- كيف تتجنب تكراره؟
- أدرج الاستدعاء المؤجل في فحص closure.
اختبر فهمك
1. هل يمكن استدعاء Proc لاحقا بأمان لمجرد كونها كائنا؟
اعرض الحل المشروح
ليس دون فحص الحالة الملتقطة وأهداف التحكم. قد تتجاوز العودة عمر طريقة التعريف، وقد تصبح الموارد والقيم قديمة أو مشتركة. اختر سلوك العودة المطلوب وحدّد الملكية والعمر وافحص الاستخدام المؤجل. لا ينشئ تخزين الكائن سياقا مستقبليا صالحا.
2. لماذا قد يهم اختيار الأقواس المعقوفة أو do/end عند استدعاءات متداخلة؟
اعرض الحل المشروح
قد تربط أسبقيتهما الكتلة بطريقة غير المقصودة. استخدم أقواسا صريحة أو افصل التعبير ثم تحقق من المستلم والمستدعي. الوضوح جزء من عقد النداء؛ فلا يفيد اختصار يخفي المالك أو يغير عدد الاستدعاءات.
أهم ما تعلمته
- تُقرأ قواعد المعاملات والعودة والالتقاط والعمر معا.
- ليست الكتلة أو Proc متزامنة أو دائمة أو معزولة تلقائيا.