تعليمة إخراج ناتج
تحوي هذه المقالة أو هذا القسم ترجمة آلية. |
تعليمة إخراج ناتج (بالإنجليزية: Return statement)حيث في برمجة الكمبيوتر، يتسبب بيان الإرجاع في ترك التنفيذ للروتين الفرعي الحالي واستئنافه عند النقطة في الكود مباشرة بعد التعليمات التي تسمى الروتين الفرعي، والمعروف باسم عنوان الإرجاع الخاص به . يتم حفظ عنوان المرسل من خلال روتين الاستدعاء، اليوم عادة في مكدس نداءات العملية أو في سجل. تسمح عبارات الإرجاع في العديد من اللغات للدالة بتحديد قيمة إرجاع ليتم تمريرها مرة أخرى إلى الكود الذي يسمى الوظيفة.
ملخص
في لغة برمجة سي وسي ++، قم return exp ;
(حيث exp
عبارة عن تعبير) هو بيان يخبر الدالة بإرجاع تنفيذ البرنامج إلى الوظيفة المستدعية، والإبلاغ عن قيمة exp
. إذا كانت الوظيفة تحتوي على نوع الإرجاع فارغ، فيمكن استخدام تعليمة الإرجاع بدون قيمة، وفي هذه الحالة ينفصل البرنامج عن الوظيفة الحالية ويعود إلى الوظيفة المستدعية.
في باسكال لا يوجد بيان عودة. (ومع ذلك، في باسكال الأحدث، يمكن استخدام Exit(exp);
لإرجاع قيمة على الفور. بدون معلمات، فقط يكسر الإجراء.) يعود الروتين الفرعي تلقائيًا عندما يصل التنفيذ إلى آخر جملة قابلة للتنفيذ. يمكن إرجاع القيم عن طريق التخصيص لمعرف له نفس اسم الروتين الفرعي، وهي وظيفة في مصطلحات باسكال. بهذه الطريقة يتم استخدام معرف الوظيفة للمكالمات المتكررة وكحامل النتيجة؛ هذا مشابه لغويًا لمعامل إخراج صريح. يتم استخدام نفس الصيغة في فورتران 66 وفورتران 77 على الرغم من إضافة عبارة إرجاع في فورتران II . في بعض اللغات الأخرى، يتم استخدام متغير نتيجة محدد بواسطة المستخدم بدلاً من معرف الوظيفة.
يحتوي أوبيرون (Oberon-07) على شرط إرجاع بدلاً من تعليمة ريترن (Return). يتم وضع بند الإرجاع بعد البيان الأخير لهيئة الإجراء. يتيح ذلك التحقق من وقت الترجمة لقيمة الإرجاع والإرجاع المناسبة من الإجراء.
تسمح بعض لغات البرمجة الموجهة للتعبير، مثل ليسب وبيرل وروبي، للمبرمج بحذف عبارة إرجاع صريحة، مع تحديد بدلاً من ذلك أن آخر تعبير تم تقييمه هو القيمة المرتجعة للروتين الفرعي.
في حالات أخرى، يتم إرجاع القيمة نول إذا لم يكن هناك بيان إرجاع صريح: في بايثون، None
عند حذف عبارة الإرجاع، بينما في جافا سكريبت يتم إرجاع undefined
في ويندوز باور شيل جميع أشكال التعبير تقييمها والتي لا يتم القبض (على سبيل المثال، تعيين متغير، يلقي إلى الفراغ أو الأنابيب إلى $ لاغية) يتم إرجاعها من روتين كعناصر في صفيف، أو ككائن واحد في حالة أن كائن واحد فقط لم يتم القبض عليه.
في لغة Perl، يمكن أن تعتمد القيمة المرتجعة أو قيم الروتين الفرعي على السياق الذي تم استدعاؤه فيه. التمييز الأساسي هو السياق القياسي حيث يتوقع رمز الاستدعاء قيمة واحدة، سياق قائمة حيث يتوقع رمز الاستدعاء قائمة من القيم وسياق فارغ حيث لا يتوقع رمز الاستدعاء أي قيمة مرتجعة على الإطلاق. يمكن أن يتحقق روتين فرعي من السياق باستخدام وظيفة wantarray
يتم استخدام بناء جملة خاص للإرجاع بدون وسيطات لإرجاع قيمة غير محددة في سياق الحجمي وقائمة فارغة في سياق القائمة. يمكن تقسيم السياق القياسي إلى سياقات منطقية ورقم وسلسلة وأنواع مرجعية مختلفة. أيضًا، يمكن إرجاع كائن حساس للسياق باستخدام تسلسل إرجاع سياقي، مع تقييم كسول للقيم القياسية.
تسمح العديد من أنظمة التشغيل للبرنامج بإرجاع نتيجة (منفصلة عن المخرجات العادية) عند انتهاء العملية؛ يشار إلى هذه القيم باسم رموز الإرجاع، أو بشكل أكثر تحديدًا حالات الخروج. كمية المعلومات التي يمكن تمريرها بهذه الطريقة محدودة للغاية، وغالبًا ما تقتصر في الممارسة العملية على الإشارة إلى النجاح أو الفشل. من داخل البرنامج، يتم تحقيق هذا الإرجاع عادةً عن طريق استدعاء Exit (استدعاء النظام) (شائع حتى في C، حيث تتوفر آلية بديلة للعودة من الوظيفة الرئيسية).
بناء الجملة
تأتي عبارات الإرجاع في أشكال عديدة. الصيغ التالية هي الأكثر شيوعًا:
لغة | بيان العودة | إذا تم حذف القيمة، قم بإرجاعها |
---|---|---|
أيدا (لغة برمجة)، بورن شيل، [1] C، C ++، جافا، بي إتش بي، سي شارب، جافا سكريبت، D | return value;
|
في بورن شيل، قيمة الخروج من آخر أمر تم تنفيذه في الوظيفة
في C [2] و C ++، [3] سلوك غير معرف إذا كانت الوظيفة إرجاع القيمة في جافا سكريبت، [5] تُرجع القيمة في جافا وسي شارب، غير مسموح بها إذا كانت الوظيفة إرجاع القيمة |
أساسي | RETURN
|
|
لثغة | (return value)
|
قيمة البيان الأخير |
بيرل، روبي | return @values;
return $value;
return;
|
قيمة البيان الأخير |
بيرل / أنا |
العودة (التعبير)؛ إرجاع؛ |
سلوك غير محدد إذا تم التصريح عن الإجراء بأنه إرجاع قيمة |
بايثون | return value
|
None
|
حديث قصير | ^ value
|
|
تى سى ال | return
return $value
return -code error "Error message"
|
قيمة البيان الأخير |
البصرية الأساسية . صافي | Return value
|
|
نوافذ بوويرشيل | return value;
|
موضوع |
تجميع x86 | ret
|
محتويات سجل eax (عن طريق الاتفاقيات) |
في بعض لغات التجميع، على سبيل المثال، بالنسبة لتقنية المعالج موس تكنولوجي 6502، يتم استخدام العودة من الروتين الفرعي (بالإنجليزية: (RTS)ReTurn from Subroutine).
عبارات عودة متعددة
اللغات التي تحتوي على بيان عودة صريح تخلق إمكانية عبارات إرجاع متعددة في نفس الوظيفة. سواء كان هذا أمرًا جيدًا أم لا، فهو أمر مثير للجدل.
يتأكد أنصار البرمجة المهيكلة الأقوياء من أن كل وظيفة لها مدخل واحد ومخرج واحد (SESE). وبالتالي، فقد قيل [6] أنه ينبغي على المرء تجنب استخدام بيان الإرجاع الصريح إلا في نهاية النص من روتين فرعي، مع الأخذ في الاعتبار أنه عند استخدامه «للعودة مبكرًا»، فقد يعاني من نفس النوع من المشاكل التي تنشأ عن بيان GOTO. على العكس من ذلك، يمكن القول إن استخدام تعليمة الإرجاع مفيد عندما يكون البديل هو رمز أكثر تعقيدًا، مثل التداخل الأعمق، مما يضر بالقراءة.
في كتابه المدرسي لعام 2004، كتب ديفيد وات أن «تدفقات التحكم في الدخول المتعدد والمخارج تكون مرغوبة في كثير من الأحيان». باستخدام مفهوم إطار عمل تينينت (Tennent) الخاص بـ المنظم (Sequencer)، يصف وات بشكل موحد تركيبات تدفق التحكم الموجودة في لغات البرمجة المعاصرة ويحاول شرح سبب تفضيل أنواع معينة من أجهزة التسلسل على الأنواع الأخرى في سياق تدفقات التحكم متعدد المخارج. يكتب وات أن goos غير المقيدة (متسلسلات القفز) سيئة لأن وجهة القفزة لا تشرح نفسها لقارئ البرنامج حتى يجد القارئ ويفحص التسمية أو العنوان الفعلي الذي هو هدف القفزة. في المقابل، يجادل وات بأن القصد المفاهيمي لمسلسل العودة واضح من سياقه الخاص، دون الحاجة إلى فحص وجهته. علاوة على ذلك، يكتب وات أن فئة من أجهزة التسلسل المعروفة باسم «متسلسلات الهروب»، والتي تُعرف باسم «جهاز التسلسل الذي ينهي تنفيذ أمر أو إجراء يتضمن نصًا»، يشمل كلا من الفواصل من الحلقات (بما في ذلك الفواصل متعددة المستويات) وبيانات الإرجاع. يلاحظ وات أيضًا أنه في حين تم تقييد متسلسلات القفز (gotos) إلى حد ما في لغات مثل سي، حيث يجب أن يكون الهدف داخل الكتلة المحلية أو كتلة خارجية شاملة، فإن هذا التقييد وحده لا يكفي لجعل القصد من جوتوز في سي سيلف - الوصف وبالتالي لا يزال بإمكانهم إنتاج «كود السباغيتي». يفحص وات أيضًا كيف تختلف متواليات الاستثناءات عن متواليات الهروب والقفز؛ للحصول على تفاصيل حول هذا راجع المقالة حول البرمجة المهيكلة.[7]
ووفقا للدراسات التجريبية التي ذكرها اريك روبرتس S.، كان المبرمجين الطالب صعوبة وضع حلول صحيحة لعدة مشاكل بسيطة في لغة مثل باسكال، الذي لا يسمح نقاط الخروج متعددة. بالنسبة لمشكلة كتابة دالة للبحث الخطي عن عنصر في مصفوفة، وجدت دراسة أجراها هنري شابيرو عام 1980 (استشهد بها روبرتس) أنه باستخدام هياكل التحكم التي يوفرها باسكال فقط، تم إعطاء الحل الصحيح بنسبة 20٪ فقط من الأشخاص. بينما لم يكتب أي موضوع رمزًا غير صحيح لهذه المشكلة إذا سمح لكتابة إرجاع من منتصف الحلقة.[8]
يجادل آخرون، بما في ذلك كينت بيك ومارتن فاولر، بأن جملة أو أكثر من جمل الحماية - عبارات العودة «للخروج المبكر» الشرطي بالقرب من بداية الوظيفة - غالبًا ما تجعل قراءة الدالة أسهل من القراءة البديلة.[9] [10] [11] [12]
المشكلة الأكثر شيوعًا في الإنهاء المبكر هي عدم تنفيذ عمليات التنظيف أو العبارات النهائية - على سبيل المثال، الذاكرة المخصصة ليست غير مخصصة، أو الملفات المفتوحة ليست مغلقة، مما يتسبب في حدوث تسريبات. يجب أن يتم ذلك في كل موقع إرجاع، حيث يكون هشًا ويمكن أن ينتج عنه أخطاء بسهولة. على سبيل المثال، في التطوير اللاحق، يمكن للمطور أن يتجاهل بيان الإرجاع، وقد لا يتم تنفيذ الإجراء الذي يجب تنفيذه في نهاية روتين فرعي (على سبيل المثال، بيان التتبع) في جميع الحالات. اللغات التي لا تحتوي على تعليمة عودة، مثل لغة باسكال القياسية، لا تعاني من هذه المشكلة. تستخدم بعض اللغات، مثل C ++ وبايثون، مفاهيم تسمح بتنفيذ الإجراءات تلقائيًا عند العودة (أو رمي الاستثناءات) مما يخفف من بعض هذه المشكلات - وغالبًا ما تُعرف هذه باسم «المحاولة / النهائية» أو ما شابه ذلك. يمكن تنفيذ وظائف مثل هذه الجمل «النهائية» من خلال الانتقال إلى نقطة العودة الفردية للروتين الفرعي. الحل البديل هو استخدام فك الرصة العادي (إلغاء التخصيص المتغير) عند خروج الوظيفة لإلغاء تخصيص الموارد، مثل عبر المدمرات على المتغيرات المحلية، أو آليات مماثلة مثل بيان بايثون «مع».
قامت بعض التطبيقات المبكرة للغات مثل باسكال و ++C الأصلي بتقييد الأنواع التي يمكن إرجاعها بواسطة دالة (على سبيل المثال، عدم دعم أنواع التسجيلات أو الهياكل) لتبسيط مترجميها.
في لغة البرمجة جافا -واللغات المماثلة على غرار ذلك، مثل جافا سكريبت -من هو ممكن لتنفيذ التعليمات البرمجية حتى بعد بيان المقابل، لأن منع أخيرا من هيكل محاولة اللحاق يتم تنفيذ دائما. لذلك إذا تم وضع تعليمة الإرجاع في مكان ما داخل كتل تراي أو كاتش، فسيتم تنفيذ الكود في النهاية (إذا تمت إضافته). حتى أنه من الممكن تغيير قيمة الإرجاع لنوع غير بدائي (خاصية لكائن تم إرجاعه بالفعل) لأن الخروج يحدث بعد ذلك أيضًا.[13]
بيانات العائد
عبارات كوزين تو ريترن هي عبارات العائد: حيث تؤدي العودة إلى إنهاء روتين فرعي، يؤدي العائد إلى تعليق روتين مشترك. سيستمر كوروتين لاحقًا من حيث تم تعليقه إذا تم استدعاؤه مرة أخرى. تعتبر كوروتين أكثر انخراطًا في التنفيذ من الإجراءات الفرعية، وبالتالي فإن العبارات الناتجة أقل شيوعًا من عبارات الإرجاع، ولكنها موجودة في عدد من اللغات.
تسلسل المكالمة / العودة
عدد من تسلسلات الاستدعاء / الإرجاع المحتملة ممكنة اعتمادًا على مجموعة تعليمات الأجهزة، بما في ذلك ما يلي:
- تقوم
CALL
بدفع عنوان الإرشاد التالي على المكدس والفروع إلى العنوان المحدد.RETURN
عنوان المرسل من المكدس إلى مؤشر التعليمات ويستأنف التنفيذ على هذا العنوان. (أمثلة x86، PDP-11). - تضع تعليمات
CALL
عنوان التعليمات التالية في السجل والفروع على العنوان المحدد.RETURN
عنوان المرسل من السجل في مؤشر التعليمات ويستأنف التنفيذ في ذلك العنوان. (مثال IBM System / 360). - تضع تعليمات
CALL
عنوان التعليمات التالية (أو الحالية) في موقع التخزين في عنوان المكالمة والفروع إلى العنوان المحدد + 1.RETURN
إلى عنوان المرسل من خلال قفزة غير مباشرة إلى التعليمات الأولى من الروتين الفرعي. (أمثلة IBM 1130، SDS9XX).
انظر أيضًا
مراجع
- ^ in the Bourne shell, only integers in the range 0-255 may be returned: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#return نسخة محفوظة 5 نوفمبر 2021 على موقع واي باك مشين.
- ^ https://msdn.microsoft.com/en-us/library/sta56yeb.aspx MSDN: return Statement (C) نسخة محفوظة 2017-07-17 على موقع واي باك مشين.
- ^ https://msdn.microsoft.com/en-us/library/k68ktdwf.aspx MSDN: return Statement (C++) نسخة محفوظة 2018-09-24 على موقع واي باك مشين.
- ^ "PHP: return - Manual". PHP Manual. The PHP Group. مؤرشف من الأصل في 2021-10-30. اطلع عليه بتاريخ 2013-03-26.
- ^ "Return - Javascript". MDN Javascript Reference. Mozilla Developer Network. مؤرشف من الأصل في 2013-05-27. اطلع عليه بتاريخ 2013-03-27.
- ^ C++ Notes: Function return Statement نسخة محفوظة 2021-04-21 على موقع واي باك مشين.
- ^ David Anthony Watt؛ William Findlay (2004). Programming language design concepts. John Wiley & Sons. ص. 215-221. ISBN:978-0-470-85320-7.
- ^ Roberts, E. [1995] “Loop Exits and Structured Programming: Reopening the Debate,” ACM SIGCSE Bulletin, (27)1: 268–272.
- ^ Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts. "Refactoring: Improving the Design of Existing Code (Google eBook)". section "Replace Nested Conditional with Guard Clauses". 2012. p. 237, p. 250. quote: "... one exit point mentality ... I don't follow the rule about one exit point from a method." نسخة محفوظة 17 أبريل 2015 على موقع واي باك مشين.
- ^ Kent Beck. "Implementation Patterns". 2007. "Chapter 7: Behavior", section "Guard Clause". نسخة محفوظة 1 أكتوبر 2016 على موقع واي باك مشين.
- ^ "Multiple return statements" نسخة محفوظة 2020-08-01 على موقع واي باك مشين.
- ^ Fred Swartz. "Return statements and the single exit fantasy". نسخة محفوظة 2020-02-23 على موقع واي باك مشين.
- ^ The finally Block,The Java Tutorials نسخة محفوظة 15 سبتمبر 2021 على موقع واي باك مشين.