هذه ثلاث طرق يتعامل بها Ruby مع chunks of code as data. block يتم تمريره إلى method (وليس object)؛ Proc و lambda هما objects تغلفان block (callable, storable). يختلف Procs و lambdas بشكل طفيف في فحص الوسائط و سلوك return.
هذه ثلاث طرق يتعامل بها Ruby مع chunks of code as data. block يتم تمريره إلى method (وليس object)؛ Proc و lambda هما objects تغلفان block (callable, storable). يختلف Procs و lambdas بشكل طفيف في فحص الوسائط و سلوك return.
[1, 2, 3].each { |n| puts n } # the { } is a block — passed to each
# a block is NOT an object; it's part of the method call, can't be stored in a variable directly
block هو الكود الذي يتم تمريره إلى method (في { } أو do...end) — إنه ليس object مستقل يمكنك تخزينه؛ إنه مرتبط بـ method call.
# a Proc — a block turned into an object you can store and call
square = Proc.new { |x| x * x }
square.call(5) # 25
square.(5) # 25 (alternate call syntax)
# a lambda — also a callable object (a "stricter" Proc)
double = lambda { |x| x * 2 }
double = ->(x) { x * 2 } # the -> "stabby lambda" syntax
double.call(5) # 10
Procs و lambdas تغلفان block إلى object يمكنك تعيينه إلى متغيرات وتمريره حولك واستدعاؤه لاحقاً (.call) — مفيد لتخزين السلوك القابل لإعادة الاستخدام.
1. ARGUMENT CHECKING:
lambda → STRICT: errors if wrong number of arguments (like a method)
proc → LENIENT: ignores extra args, fills missing with nil
2. RETURN behavior:
lambda → `return` returns from the LAMBDA (like a normal method)
proc → `return` returns from the ENCLOSING METHOD (can surprise you!)
def test_proc
p = Proc.new { return 10 }
p.call # returns from test_proc ENTIRELY → 10
return 20 # never reached!
end
def test_lambda
l = lambda { return 10 }
l.call # returns from the LAMBDA only → 10
return 20 # reached → test_lambda returns 20
end
الفرق الأهم: lambda يتصرف مثل method (وسائط صارمة، return يخرج من lambda فقط)، بينما proc أكثر تساهلاً (يتجاهل عدم تطابق الوسائط، و return يخرج من الـ enclosing method — مما قد يسبب سلوكاً مفاجئاً). Lambdas يُفضل عموماً لسلوكها الشبيه بـ method والمتوقع.
فهم blocks و procs و lambdas — وخاصة اختلافاتهم — معرفة Ruby مهمة تعكس فهماً أعمق لكيفية تعامل Ruby مع الكود كـ data. Blocks الأكثر شيوعاً (تُمرر إلى methods للتكرار والـ callbacks — السمة المميزة لـ Ruby)، بينما procs و lambdas تحول blocks إلى objects قابلة للتخزين وإعادة الاستخدام يمكنك تعيينها إلى متغيرات وتمريرها حولك واستدعاؤها لاحقاً (مفيدة لتخزين السلوك وبناء الأنماط الوظيفية وتمرير callbacks كقيم).
الفروقات الرئيسية بين procs و lambdas دقيقة لكنها مهمة وموضوع متكرر في المقابلات: فحص الوسائط (lambdas صارمة مثل methods، procs متساهلة) وخاصة سلوك return (return في lambda يخرج من lambda فقط، بينما return في proc يخرج من الـ enclosing method — مما قد يسبب سلوكاً مفاجئاً وصعب التصحيح).
فهم هذه التمييزات — أن lambda يتصرف مثل method (صارم ومتوقع مع return محلي) بينما proc أكثر تساهلاً مع دلالات return مفاجئة — مهم لاستخدامها بشكل صحيح وللتوصية الشائعة بـ تفضيل lambdas لسلوكها الآمن والشبيه بـ method.
بينما blocks هي Ruby يومية و procs/lambdas تُستخدم للـ callbacks القابلة للتخزين والأنماط الوظيفية، فإن فهم الثلاثة جميعاً (خاصة فروقات proc-vs-lambda return والوسائط) يعكس معرفة Ruby قوية، يساعدك على تجنب gotcha proc-return، وهو موضوع مقابلة كلاسيكي يميز المطورين الذين يفهمون حقاً كيفية تعامل Ruby مع الكود كـ objects.