لماذا صريحة العودة فرقا في بروك?
-
07-07-2019 - |
سؤال
def foo
f = Proc.new { return "return from foo from inside proc" }
f.call # control leaves foo here
return "return from foo"
end
def bar
b = Proc.new { "return from bar from inside proc" }
b.call # control leaves bar here
return "return from bar"
end
puts foo # prints "return from foo from inside proc"
puts bar # prints "return from bar"
اعتقدت return
الكلمة كان اختياري في روبي و انك دائما return
جي سواء طلب ذلك أو لا.بالنظر إلى أن أجد أنه من المستغرب أن foo
و bar
يكون الإخراج المختلفة على الرغم من حقيقة أن foo
يحتوي على صريح return
في Proc f
.
لا أحد يعرف لماذا هذا هو الحال ؟
المحلول
روبي ثلاثة ثوابت:
- A كتلة ليس كائن تم إنشاؤه من قبل
{
...}
أوdo
...end
. - A proc هو
Proc
كائن تم إنشاؤه من قبلProc.new
أوproc
. - A امدا هو
Proc
تم إنشاؤها من قبلlambda
(أوproc
في روبي 1.8).
روبي ثلاث كلمات أن يعود من شيء:
return
ينهي طريقة أو امدا في.next
ينهي كتلة, بروك, أو امدا في.break
ينهي الطريقة التي تسفر عن كتلة أو الاحتجاج بروك أو امدا في.
في lambdas, return
يتصرف مثل next
, مهما كانت الأسباب. next
و break
تسمى الطريقة التي هي لأنها هي الأكثر شيوعا مع أساليب مثل each
, حيث إنهاء كتلة سوف يؤدي التكرار إلى السيرة الذاتية مع القادم عنصر من المجموعة وإنهاء each
سوف يسبب لك كسر الخروج من الحلقة.
إذا كنت تستخدم
return
داخل تعريف foo
, سوف يعود من foo
, حتى لو كان داخل كتلة أو proc.العودة من كتلة ، يمكنك استخدام next
الكلمة بدلا من ذلك.
def foo
f = Proc.new { next "return from foo from inside proc" }
f.call # control leaves foo here
return "return from foo"
end
puts foo # prints "return from foo"
نصائح أخرى
هذه هي دلالات على Proc
s ؛ ليس بالضرورة دلالات لجميع الكتل.أنا أوافق هذا هو مربكا بعض الشيء.ومن هناك لمزيد من المرونة (وربما جزئيا سبب روبي لديه المواصفات باستثناء تنفيذه).
السلوك هو محدد في Proc
التنفيذ. Lambda
s تتصرف بشكل مختلف, لذلك إذا كنت تريد الخاص بك return
s لا خروج من أرفق طريقة استخدام lambdas.أو حذف return
الكلمة من Proc
.
تحقيق عميق من Rubys الإغلاق هنا.أنها رائعة فضح.
لذلك:
def foo
f = Proc.new {
p2 = Proc.new { return "inner proc"};
p2.call
return "proc"
}
f.call
return "foo"
end
def foo2
result = Proc.new{"proc"}.call
"foo2 (proc result is: #{result})"
end
def bar
l = lambda { return "lambda" }
result = l.call
return "bar (lambda result is: #{result})"
end
puts foo
# inner proc
puts foo2
# foo (proc result is: proc)
puts bar
# bar (lambda result is: lambda)
وأعتقد أنه من هذا الطريق: Proc.new مجرد خلق كتلة من التعليمات البرمجية التي هي جزء من وظيفة الدعوة. إجراءات / امدا خلق وظيفة مجهولة المصدر التي لديها ارتباطات خاصة. وهناك أمثلة التعليمات البرمجية صغيرة تساعد:
def foo
f = Proc.new { return "return from foo from inside Proc.new" }
f.call # control leaves foo here
return "return from foo"
end
وما يعادل
def foo
begin
return "return from foo from inside begin/end" }
end
return "return from foo"
end
وهكذا فمن الواضح أن وعودة فقط العودة من وظيفة "فو '
وعلى النقيض:
def foo
f = proc { return "return from foo from inside proc" }
f.call # control stasy in foo here
return "return from foo"
end
وما يعادل (تجاهل الارتباطات نظرا لعدم المستخدمة في هذا المثال):
def unonymous_proc
return "return from foo from inside proc"
end
def foo
unonymous_proc()
return "return from foo"
end
والذي هو كما هو واضح لن يعود من فو والاستمرار في العبارة التالية بدلا من ذلك.