الوظيفة (برمجة الحاسوب)

في برمجة الحاسوب ، الدالة (وأيضًا الإجراء ، أو الطريقة ، أو الروتين الفرعي ، أو الروتين ، أو البرنامج الفرعي ) هي وحدة قابلة للاستدعاء [ 1 ] من منطق البرمجيات التي لها واجهة وسلوك جيدين ويمكن استدعاؤها عدة مرات.

تُعدّ الوحدات القابلة للاستدعاء أداة برمجة قوية. [ 2 ] يتمثل الغرض الأساسي منها في السماح بتقسيم مشكلة كبيرة و/أو معقدة إلى أجزاء ذات عبء معرفي منخفض نسبيًا ، وتخصيص أسماء ذات دلالة لهذه الأجزاء (إلا إذا كانت مجهولة). يمكن للتطبيق المدروس لهذه الوحدات أن يقلل من تكلفة تطوير البرمجيات وصيانتها، مع زيادة جودتها وموثوقيتها. [ 3 ]

تتواجد الوحدات القابلة للاستدعاء على مستويات تجريد متعددة في بيئة البرمجة. [ 4 ] على سبيل المثال، قد يكتب المبرمج دالةً في شفرة المصدر تُترجم إلى شفرة الآلة، وتُنفذ دلالات متشابهة . توجد وحدة قابلة للاستدعاء في شفرة المصدر، وأخرى مرتبطة بها في شفرة الآلة، لكنهما نوعان مختلفان من الوحدات القابلة للاستدعاء ، ولكل منهما دلالات وخصائص مختلفة.

مصطلحات

تُفرّق بعض لغات البرمجة ، مثل كوبول وبيسك ، بين الدوال التي تُرجع قيمة (وتُسمى عادةً "دوال") وتلك التي لا تُرجع قيمة (وتُسمى عادةً "برامج فرعية" أو "إجراءات")؛ بينما تستخدم لغات أخرى ، مثل سي وسي++ وراست ، مصطلح "دالة" فقط بغض النظر عما إذا كانت تُرجع قيمة أم لا؛ وتستخدم لغات أخرى، مثل ألغول 60 وبي إل/آي ، كلمة " إجراء " فقط . وتشير بعض لغات البرمجة كائنية التوجه ، مثل جافا وسي شارب ، إلى الدوال داخل الأصناف باسم " طرق ".

تاريخ

طُرحت فكرة الوحدة القابلة للاستدعاء لأول مرة على يد جون موتشلي وكاثلين أنتونيلي أثناء عملهما على جهاز إينياك، وسُجّلت في ندوة بجامعة هارفارد في يناير 1947 بعنوان "إعداد مسائل لأجهزة من نوع إيدفاك ". [ 5 ] يُنسب الفضل عمومًا إلى موريس ويلكس وديفيد ويلر وستانلي جيل في ابتكار هذا المفهوم رسميًا، والذي أطلقوا عليه اسم " الروتين الفرعي المغلق" ، [ 6 ] [ 7 ] في مقابل "الروتين الفرعي المفتوح" أو "الماكرو" . [ 8 ] مع ذلك، ناقش آلان تورينج الروتينات الفرعية في ورقة بحثية عام 1945 حول مقترحات تصميم جهاز NPL ACE ، بل وذهب إلى حد ابتكار مفهوم مكدس عناوين الإرجاع . [ 9 ]

طُورت فكرة الروتين الفرعي بعد أن كانت أجهزة الحوسبة موجودة بالفعل لبعض الوقت. كانت تعليمات العمليات الحسابية والقفزات الشرطية مُخططًا لها مسبقًا ولم تتغير كثيرًا، لكن التعليمات الخاصة المستخدمة لاستدعاء الإجراءات شهدت تغييرات كبيرة على مر السنين. لم تكن أجهزة الكمبيوتر الأولى، مثل مانشستر بيبي ، وبعض المعالجات الدقيقة المبكرة، مثل آر سي إيه 1802 ، تحتوي على أي تعليمة لاستدعاء روتين فرعي. كان من الممكن تنفيذ الروتينات الفرعية، لكنها كانت تتطلب من المبرمجين استخدام تسلسل الاستدعاء - وهو سلسلة من التعليمات - في كل موقع استدعاء .

تم تنفيذ روتين فرعي واحد في عام 1945 في جهاز Z4 الخاص بكونراد تسوزه على شكل شريط. [ 10 ]

في عام 1945، استخدم آلان تورينج مصطلحي "الدفن" و"إلغاء الدفن" كوسيلة لاستدعاء البرامج الفرعية والعودة منها. [ 11 ] [ 12 ]

في يناير 1947، قدّم جون ماوكلي ملاحظات عامة في ندوة حول آلات الحوسبة الرقمية واسعة النطاق، برعاية مشتركة من جامعة هارفارد ومكتب الذخائر التابع للبحرية الأمريكية. يناقش فيها التشغيل التسلسلي والمتوازي، مقترحًا ما يلي:

...لا داعي لتعقيد بنية الجهاز على الإطلاق. فمن الممكن، بما أن جميع الخصائص المنطقية الأساسية لهذه العملية متوفرة، تطوير تعليمات برمجية لوضع الإجراءات الفرعية في الذاكرة في أماكن معروفة للجهاز، وبطريقة يسهل استدعاؤها واستخدامها.

بمعنى آخر، يمكن تحديد الروتين الفرعي A للقسمة، والروتين الفرعي B للضرب المركب، والروتين الفرعي C لحساب الخطأ المعياري لسلسلة من الأرقام، وهكذا دواليك في قائمة الروتينات الفرعية اللازمة لحل مسألة معينة. ... تُخزَّن جميع هذه الروتينات الفرعية في الجهاز، وكل ما يلزم هو الإشارة إليها باختصار برقمها، كما هو موضح في الشفرة. [ 5 ]

عملت كاي ماكنولتي عن كثب مع جون موتشلي في فريق إينياك، وطورت فكرةً لبرامج فرعية لجهاز إينياك الذي كانت تبرمجه خلال الحرب العالمية الثانية. [ 13 ] وقد استخدمت هي ومبرمجو إينياك الآخرون هذه البرامج الفرعية للمساعدة في حساب مسارات الصواريخ. [ 13 ]

كتب غولدستين وفون نيومان ورقة بحثية بتاريخ 16 أغسطس 1948 تناقش استخدام البرامج الفرعية. [ 14 ]

بعض الحواسيب والمعالجات الدقيقة القديمة جدًا، مثل IBM 1620 و Intel 4004 و Intel 8008 ووحدات التحكم الدقيقة PIC ، تستخدم استدعاء روتين فرعي بتعليمات واحدة، حيث تستخدم مكدسًا مخصصًا لتخزين عناوين العودة؛ يدعم هذا النوع من الأجهزة مستويات قليلة فقط من تداخل الروتينات الفرعية، ولكنه يدعم الروتينات الفرعية المتكررة. أما الأجهزة التي صُنعت قبل منتصف الستينيات، مثل UNIVAC I و PDP-1 و IBM 1130 ، فكانت تستخدم عادةً اصطلاح استدعاء يحفظ عداد التعليمات في أول موقع ذاكرة للروتين الفرعي المُستدعى. يسمح هذا بمستويات عميقة من تداخل الروتينات الفرعية، ولكنه لا يدعم الروتينات الفرعية المتكررة. كان لدى IBM System/360 تعليمة استدعاء روتين فرعي تضع قيمة عداد التعليمات المحفوظة في سجل للأغراض العامة؛ وبإضافة بعض التعليمات البرمجية، يمكن استخدام هذه التعليمة لدعم مستويات عميقة من تداخل الروتينات الفرعية والروتينات الفرعية المتكررة. يُعد جهاز Burroughs B5000 [ 15 ] (1961) أحد أوائل أجهزة الكمبيوتر التي تخزن بيانات الإرجاع الفرعية على مكدس.

يُعدّ جهاز DEC PDP-6 [ 16 ] (1964) من أوائل الأجهزة التي تعتمد على المُراكم، والتي احتوت على تعليمة استدعاء روتين فرعي تحفظ عنوان العودة في مكدس يُشار إليه بواسطة مُراكم أو سجل فهرسة. وقد حذت حذوه لاحقًا أجهزة PDP-10 (1966) و PDP-11 (1970) و VAX-11 (1976)؛ كما تدعم هذه الميزة كلاً من تداخل الروتينات الفرعية العميق والروتينات الفرعية المتكررة. [ 17 ]

الدعم اللغوي

في بدايات برامج التجميع، كان دعم البرامج الفرعية محدودًا. لم تكن البرامج الفرعية مفصولة صراحةً عن بعضها البعض أو عن البرنامج الرئيسي، بل كان من الممكن أن يتداخل رمز البرنامج الفرعي مع رموز برامج فرعية أخرى. وقد وفرت بعض برامج التجميع وحدات ماكرو مُعرَّفة مسبقًا لإنشاء تسلسلات الاستدعاء والإرجاع. وبحلول ستينيات القرن العشرين، أصبحت برامج التجميع تتمتع بدعم أكثر تطورًا للبرامج الفرعية المضمنة والمنفصلة التي يمكن ربطها معًا.

كانت لغة فورتران 2 من أوائل لغات البرمجة التي تدعم البرامج الفرعية والدوال التي يكتبها المستخدم . وقد تم إصدار مترجم فورتران 2 من شركة IBM في عام 1958. كما دعمت لغة ALGOL 58 وغيرها من لغات البرمجة المبكرة البرمجة الإجرائية.

المكتبات

على الرغم من هذا الأسلوب المعقد، أثبتت البرامج الفرعية فائدتها الكبيرة. فقد سمحت باستخدام نفس الكود في العديد من البرامج المختلفة. كانت الذاكرة مورداً نادراً جداً في الحواسيب القديمة، وقد ساهمت البرامج الفرعية في توفير كبير في حجم البرامج.

كانت العديد من الحواسيب القديمة تُحمّل تعليمات البرنامج في الذاكرة من شريط ورقي مثقوب . وكان بالإمكان توفير كل روتين فرعي بواسطة شريط منفصل، يُحمّل أو يُلصق قبل أو بعد البرنامج الرئيسي (أو "الخط الرئيسي" [ 18 ] )؛ وكان من الممكن استخدام شريط الروتين الفرعي نفسه بواسطة العديد من البرامج المختلفة. وقد استُخدم نهج مماثل في الحواسيب التي كانت تُحمّل تعليمات البرنامج من بطاقات مثقبة . وكان مصطلح "مكتبة الروتينات الفرعية" يعني في الأصل مكتبة، بالمعنى الحرفي، تحتفظ بمجموعات مُفهرسة من الأشرطة أو مجموعات البطاقات للاستخدام الجماعي.

العودة عن طريق القفزة غير المباشرة

ولإزالة الحاجة إلى التعليمات البرمجية ذاتية التعديل ، قام مصممو الكمبيوتر في النهاية بتوفير تعليمات قفز غير مباشرة ، والتي كان معاملها، بدلاً من أن يكون عنوان العودة نفسه، هو موقع متغير أو سجل معالج يحتوي على عنوان العودة.

في تلك الحواسيب، بدلاً من تعديل قفزة العودة للدالة، يقوم البرنامج المستدعي بتخزين عنوان العودة في متغير بحيث عند اكتمال الدالة، يقوم بتنفيذ قفزة غير مباشرة توجه التنفيذ إلى الموقع المحدد بواسطة المتغير المحدد مسبقًا.

انتقل إلى الروتين الفرعي

ومن التطورات الأخرى تعليمة الانتقال إلى الروتين الفرعي ، التي جمعت بين حفظ عنوان العودة والقفزة الاستدعائية، مما قلل من الحمل الزائد بشكل كبير. وقد وُجدت خمسة أشكال على الأقل من هذه التعليمة في خمسينيات القرن العشرين.

  • قفزة العودة: يتم تخزين عنوان العودة في الكلمة الأولى من الروتين الفرعي. تُعد قفزة العودة (RJ) على جهاز UNIVAC 1103A [ 19 ] مثالًا مبكرًا على ذلك.
  • قفزة الفهرس: تخزين عنوان العودة في سجل الفهرس. يُعدّ نقل وتعيين الفهرس (TSX) على جهاز IBM 704 [ 20 ] مثالًا مبكرًا على ذلك.
  • التخزين التلقائي في موقع تخزين مخصص: موقع Store P (STP) على RCA 501 [ 21 ] هو مثال مبكر.
  • التخزين التلقائي في سجل مخصص: سجلات التسلسل والتسلسل المشترك (SH و CSH) [ 22 ] في جهاز Honeywell 800 هي مثال مبكر.
  • تعديل عنوان العودة: تُضيف تعليمة "عنوان العودة" واحدًا إلى محتويات سجل عداد البرنامج، وتُعدِّل جزء العنوان في تعليمة التفرع عند الكلمة الأخيرة من الروتين الفرعي بعنوان العودة الخاص بالمُستدعي. وتتبع تعليمة "عنوان العودة" مباشرةً تعليمة تفرع إلى بداية الروتين الفرعي. يُعدّ LGP-30 [ 23 ] مثالًا على ذلك.

يُعدّ نظام IBM System/360 مثالًا على حفظ عنوان العودة في سجل مُخصّص. تقوم تعليمات التفرع BAL أو BALR، المُصمّمة لاستدعاء الإجراءات، بحفظ عنوان العودة في سجل المعالج المُحدّد في التعليمات، والذي يُشار إليه عادةً بالسجل رقم 14. وللعودة، يكفي أن يُنفّذ البرنامج الفرعي تعليمات تفرع غير مباشر (BR) عبر هذا السجل. إذا احتاج البرنامج الفرعي إلى هذا السجل لغرض آخر (مثل استدعاء برنامج فرعي آخر)، فإنه يحفظ محتويات السجل في موقع ذاكرة خاص أو في مكدس السجلات .

تُعدّ بنية HP 2100 مثالًا على حفظ عنوان العودة في الكلمة الأولى من الروتين الفرعي. تقوم تعليمة JSB بحفظ عنوان العودة في موقع الذاكرة الذي كان هدف التفرع. ويبدأ تنفيذ الإجراء في موقع الذاكرة التالي. في لغة التجميع الخاصة بـ HP 2100، يُكتب، على سبيل المثال،

... JSB MYSUB (يستدعي الروتين الفرعي MYSUB.) BB ... (سأعود إلى هنا بعد الانتهاء من MYSUB.) 

لاستدعاء روتين فرعي يُسمى MYSUB من البرنامج الرئيسي. سيتم ترميز الروتين الفرعي على النحو التالي:

MYSUB NOP (تخزين عنوان إرجاع MYSUB.) AA ... (بداية جسم MYSUB.) ... JMP MYSUB,I (يعود إلى البرنامج المُستدعي.) 

تضع تعليمة JSB عنوان تعليمة NEXT (أي BB) في الموقع المحدد كمعامل لها (أي MYSUB)، ثم تنتقل إلى موقع NEXT التالي (أي AA = MYSUB + 1). بعد ذلك، يمكن للبرنامج الفرعي العودة إلى البرنامج الرئيسي بتنفيذ قفزة غير مباشرة JMP MYSUB, I، والتي تنتقل إلى الموقع المخزن في MYSUB. يمكن لمترجمات لغة فورتران وغيرها من اللغات استخدام هذه التعليمات بسهولة عند توفرها. يدعم هذا الأسلوب مستويات متعددة من الاستدعاءات؛ ومع ذلك، نظرًا لأن عنوان الإرجاع والمعاملات وقيم الإرجاع للبرنامج الفرعي تُخصص لها مواقع ذاكرة ثابتة، فإنه لا يسمح بالاستدعاءات المتكررة.

بالمناسبة، استُخدمت طريقة مشابهة في برنامج لوتس 1-2-3 ، في أوائل ثمانينيات القرن الماضي، لاكتشاف تبعيات إعادة الحساب في جداول البيانات. وتحديدًا، تم حجز موقع في كل خلية لتخزين عنوان العودة . وبما أن المراجع الدائرية غير مسموح بها في ترتيب إعادة الحساب الطبيعي، فإن هذا يسمح بتتبع الشجرة دون حجز مساحة لمكدس في الذاكرة، والتي كانت محدودة للغاية في الحواسيب الصغيرة مثل حاسوب IBM الشخصي .

مكدس الاستدعاءات

تستخدم معظم التطبيقات الحديثة لاستدعاء الدوال مكدس الاستدعاءات ، وهو حالة خاصة من بنية بيانات المكدس ، لتنفيذ استدعاءات الدوال وعمليات الإرجاع. يُنشئ كل استدعاء إجراء مدخلاً جديداً، يُسمى إطار المكدس ، في أعلى المكدس؛ وعندما يُنهي الإجراء عمله، يُحذف إطار المكدس الخاص به من المكدس، ويمكن استخدام مساحته لاستدعاءات إجراءات أخرى. يحتوي كل إطار مكدس على البيانات الخاصة بالاستدعاء المقابل، والتي تتضمن عادةً معلمات الإجراء ومتغيراته الداخلية، بالإضافة إلى عنوان الإرجاع.

يمكن تنفيذ تسلسل الاستدعاء بواسطة سلسلة من التعليمات العادية (وهو نهج لا يزال يستخدم في الحوسبة ذات مجموعة التعليمات المخفضة (RISC) وبنى الكلمات الطويلة جدًا للتعليمات (VLIW))، ولكن العديد من الآلات التقليدية المصممة منذ أواخر الستينيات تضمنت تعليمات خاصة لهذا الغرض.

عادةً ما يتم تنفيذ مكدس الاستدعاءات كمنطقة متصلة من الذاكرة. ويُعدّ اختيار ما إذا كان الجزء السفلي من المكدس هو أدنى عنوان أو أعلى عنوان ضمن هذه المنطقة خيارًا تصميميًا اعتباطيًا، بحيث يمكن أن ينمو المكدس للأمام أو للخلف في الذاكرة؛ ومع ذلك، فقد اختارت العديد من البنى الخيار الأخير. [ 24 ]

استخدمت بعض التصاميم، ولا سيما بعض تطبيقات لغة فورث ، مكدسين منفصلين، أحدهما مخصص بشكل أساسي لمعلومات التحكم (مثل عناوين الإرجاع وعدادات الحلقات) والآخر للبيانات. كان المكدس الأول بمثابة مكدس استدعاءات، أو يعمل مثله، ولم يكن متاحًا للمبرمج إلا بشكل غير مباشر من خلال بنيات لغوية أخرى، بينما كان الوصول إلى المكدس الثاني أكثر مباشرة.

عندما طُرحت استدعاءات الإجراءات القائمة على المكدس لأول مرة، كان أحد أهم الدوافع هو توفير الذاكرة الثمينة. [ 25 ] مع هذه الآلية، لا يحتاج المُصرّف إلى حجز مساحة منفصلة في الذاكرة للبيانات الخاصة (المعاملات، وعنوان الإرجاع، والمتغيرات المحلية) لكل إجراء. في أي لحظة، لا يحتوي المكدس إلا على البيانات الخاصة بالاستدعاءات النشطة حاليًا ( أي تلك التي تم استدعاؤها ولكن لم تُرجع قيمة بعد). نظرًا للطرق التي كانت تُجمّع بها البرامج عادةً من المكتبات، لم يكن من النادر (ولا يزال) العثور على برامج تتضمن آلاف الدوال، لا يكون منها سوى عدد قليل نشطًا في أي لحظة. بالنسبة لمثل هذه البرامج، يمكن لآلية مكدس الاستدعاءات توفير كميات كبيرة من الذاكرة. في الواقع، يمكن اعتبار آلية مكدس الاستدعاءات أقدم وأبسط طريقة لإدارة الذاكرة تلقائيًا .

ومع ذلك، تتمثل إحدى مزايا طريقة مكدس الاستدعاءات في أنها تسمح باستدعاءات الدوال المتكررة ، حيث يحصل كل استدعاء متداخل لنفس الإجراء على نسخة منفصلة من بياناته الخاصة.

في بيئة متعددة الخيوط ، يوجد عادةً أكثر من مكدس واحد. [ 26 ] قد تستخدم البيئة التي تدعم بشكل كامل الروتينات الفرعية أو التقييم الكسول هياكل بيانات أخرى غير المكدسات لتخزين سجلات التنشيط الخاصة بها.

التكديس المتأخر

من عيوب آلية مكدس الاستدعاءات زيادة تكلفة استدعاء الإجراء وقيمة الإرجاع المقابلة له. تشمل هذه التكلفة الإضافية زيادة وإنقاص مؤشر المكدس (وفي بعض البنى، التحقق من تجاوز سعة المكدس )، والوصول إلى المتغيرات والمعاملات المحلية باستخدام عناوين نسبية للإطار، بدلاً من العناوين المطلقة. قد تتجلى هذه التكلفة في زيادة وقت التنفيذ، أو زيادة تعقيد المعالج، أو كليهما.

يُعدّ هذا العبء الإضافي واضحًا ومُزعجًا للغاية في الإجراءات الطرفية أو الدوال الطرفية ، التي تُنهي عملها دون استدعاء أي إجراء آخر. [ 27 ] [ 28 ] ولتقليل هذا العبء، تحاول العديد من المُترجمات الحديثة تأخير استخدام مكدس الاستدعاءات حتى الحاجة الفعلية إليه. على سبيل المثال، قد يخزن استدعاء الإجراء P عنوان الإرجاع ومعاملات الإجراء المُستدعى في سجلات مُعالج مُعينة، وينقل التحكم إلى جسم الإجراء عبر قفزة بسيطة. إذا أنهى الإجراء P عمله دون إجراء أي استدعاء آخر، فلن يُستخدم مكدس الاستدعاءات على الإطلاق. أما إذا احتاج P إلى استدعاء إجراء آخر Q ، فسيستخدم مكدس الاستدعاءات لحفظ محتويات أي سجلات (مثل عنوان الإرجاع) التي ستكون مطلوبة بعد انتهاء Q.

سمات

بشكل عام، الوحدة القابلة للاستدعاء هي قائمة من التعليمات التي تُنفذ بالتسلسل بدءًا من التعليمة الأولى، باستثناء ما يُحدده منطقها الداخلي. ويمكن استدعاؤها عدة مرات أثناء تنفيذ البرنامج. ويستمر التنفيذ عند التعليمة التالية لتعليمة الاستدعاء، حيث تُعيد هذه التعليمة التحكم.

التطبيقات

تطورت خصائص تطبيقات الوحدات القابلة للاستدعاء بمرور الوقت وتختلف باختلاف السياق. يصف هذا القسم خصائص التطبيقات الشائعة المختلفة.

الخصائص العامة

توفر معظم لغات البرمجة الحديثة ميزات لتعريف واستدعاء الدوال، بما في ذلك بناء الجملة للوصول إلى هذه الميزات، ومنها:

  • افصل تنفيذ دالة ما عن بقية البرنامج
  • قم بتعيين مُعرّف واسم لدالة.
  • حدد المعاملات الرسمية باسم ونوع بيانات لكل منها
  • قم بتعيين نوع البيانات للقيمة المُعادة، إن وُجدت.
  • حدد قيمة الإرجاع في جسم الدالة
  • استدعاء دالة
  • قم بتوفير المعاملات الفعلية التي تتوافق مع المعاملات الرسمية للدالة المستدعاة
  • إعادة التحكم إلى المتصل عند نقطة الاتصال
  • استهلك القيمة المُعادة في المُستدعي
  • تخلص من القيم التي تم إرجاعها بواسطة الاستدعاء
  • قم بتوفير نطاق تسمية خاص للمتغيرات
  • حدد المتغيرات الموجودة خارج الدالة والتي يمكن الوصول إليها داخلها
  • قم بنشر حالة استثنائية خارج الدالة ومعالجتها في سياق الاستدعاء.
  • قم بتجميع الوظائف في حاوية مثل وحدة نمطية أو مكتبة أو كائن أو فئة

تسمية

تستخدم بعض اللغات ، مثل باسكال وفورتران وآدا والعديد من لهجات لغة بيسك ، اسمًا مختلفًا للوحدة القابلة للاستدعاء التي تُرجع قيمة ( دالة أو برنامج فرعي ) مقابل تلك التي لا تُرجع قيمة ( إجراء فرعي أو عملية ). بينما تستخدم لغات أخرى ، مثل سي وسي++ وسي # وليسب ، اسمًا واحدًا فقط للوحدة القابلة للاستدعاء، وهو دالة . وتستخدم لغات عائلة سي الكلمة المفتاحية للإشارة إلى عدم وجود قيمة مُرجعة.void

صيغة الاستدعاء

إذا تم تعريف دالة لإرجاع قيمة، فيمكن تضمين استدعاء لها في تعبير لاستخدام القيمة المُرجعة. على سبيل المثال، يمكن استدعاء دالة الجذر التربيعي القابلة للاستدعاء على النحو التالي y = sqrt(x):

تُستدعى الوحدة القابلة للاستدعاء التي لا تُرجع قيمة كعبارة مستقلة print("hello"). ويمكن استخدام هذه الصيغة أيضًا للوحدة القابلة للاستدعاء التي تُرجع قيمة، ولكن سيتم تجاهل القيمة المُرجعة.

تتطلب بعض اللغات القديمة كلمة مفتاحية للاستدعاءات التي لا تستهلك قيمة إرجاع، مثل CALL print("hello").

حدود

تدعم معظم التطبيقات، وخاصة في اللغات الحديثة، المعاملات التي يُعلن عنها الكائن القابل للاستدعاء كمعاملات رسمية . ويُمرر المستدعي المعاملات الفعلية ، أو ما يُعرف بالوسائط ، للمطابقة. وتُوفر لغات البرمجة المختلفة اصطلاحات مختلفة لتمرير الوسائط.

مؤتمروصفيستخدم في
حسب القيمةيتم تمرير نسخة من الوسيطالوضع الافتراضي في معظم اللغات الشبيهة بلغة Algol بعد الإصدار 60 ، مثل Pascal وDelphi وSimula وCPL وPL/M وModula وOberon وAda وغيرها الكثير بما في ذلك C وC++ وJava
بالإشارةيتم تمرير مرجع إلى الوسيط، وعادةً ما يكون عنوانهيمكن اختيارها في معظم اللغات الشبيهة بلغة Algol بعد الإصدار 60 ، مثل Algol 68 وPascal وDelphi وSimula وCPL وPL/M وModula وOberon وAda وغيرها الكثير بما في ذلك C++ وFortran وPL/I
بالنتيجةيتم نسخ القيمة المحسوبة أثناء الاستدعاء إلى الوسيط عند العودةمعلمات Ada OUT
حسب القيمة والنتيجةيتم تمرير نسخة من الوسيط، ويتم نسخ القيمة المحسوبة أثناء الاستدعاء إلى الوسيط عند العودة.معاملات الإدخال والإخراج في Algol و Swift
بالاسمكما هو الحال في الماكرو - استبدل المعاملات بتعبيرات الوسائط غير المُقَيَّمة، ثم قَيِّم الوسيط في سياق المُستدعي في كل مرة يستخدم فيها الكائن القابل للاستدعاء المعاملألغول، سكالا
بالقيمة الثابتةيشبه ذلك الخاصية بالقيمة، باستثناء أن المعامل يُعامل كثابت.معلمات PL/I غير القابلة للتخصيص، معلمات Ada IN

القيمة المُعادة

في بعض لغات البرمجة، مثل BASIC، يختلف بناء الجملة (أي الكلمة المفتاحية) للدالة القابلة للاستدعاء باختلاف ما إذا كانت تُرجع قيمة أم لا. أما في لغات أخرى، فيكون بناء الجملة واحدًا بغض النظر عن ذلك. في بعض هذه اللغات، تُستخدم كلمة مفتاحية إضافية للإشارة إلى عدم وجود قيمة مُرجعة، كما هو الحال voidفي لغات C وC++ وC#. في لغات أخرى، مثل Python، يكمن الاختلاف في احتواء جسم الدالة على عبارة إرجاع مع قيمة، وقد تُرجع دالة معينة قيمة أو لا تُرجعها بناءً على مسار التحكم.

تأثيرات جانبية

في العديد من السياقات، قد يكون للدالة القابلة للاستدعاء سلوك جانبي مثل تعديل البيانات التي تم تمريرها أو البيانات العامة، أو القراءة من جهاز طرفي أو الكتابة إليه ، أو الوصول إلى ملف ، أو إيقاف البرنامج أو الجهاز، أو إيقاف تنفيذ البرنامج مؤقتًا.

يعتبر روبرت سي. مارتن ، المعروف بترويجه لمبادئ التصميم، الآثار الجانبية غير مرغوب فيها. ويجادل مارتن بأن الآثار الجانبية قد تؤدي إلى اقتران زمني أو تبعيات ترتيبية. [ 29 ]

في لغات البرمجة الوظيفية البحتة مثل هاسكل ، لا يمكن أن يكون للدالة أي آثار جانبية ، أي أنها لا تستطيع تغيير حالة البرنامج. تُعيد الدوال دائمًا نفس النتيجة لنفس المُدخلات. تدعم هذه اللغات عادةً الدوال التي تُعيد قيمة فقط، إذ لا قيمة لدالة لا تُعيد قيمة ولا تُحدث أي أثر جانبي.

المتغيرات المحلية

تدعم معظم السياقات المتغيرات المحلية - وهي ذاكرة مملوكة لدالة قابلة للاستدعاء لتخزين القيم الوسيطة. تُخزَّن هذه المتغيرات عادةً في سجل تفعيل الاستدعاء على مكدس الاستدعاءات إلى جانب معلومات أخرى مثل عنوان الإرجاع .

الاستدعاء المتداخل التكرار

إذا كانت اللغة تدعم ذلك، يمكن للدالة استدعاء نفسها، مما يؤدي إلى تعليق تنفيذها مؤقتًا أثناء تنفيذ نسخة أخرى متداخلة من نفس الدالة. يُعدّ الاستدعاء الذاتي وسيلة فعّالة لتبسيط بعض الخوارزميات المعقدة وحلّ المشكلات المعقدة. توفر لغات البرمجة التي تدعم الاستدعاء الذاتي نسخة جديدة من المتغيرات المحلية في كل استدعاء. إذا رغب المبرمج في أن تستخدم الدالة المستدعاة ذاتيًا نفس المتغيرات بدلًا من المتغيرات المحلية، فإنه عادةً ما يُعلن عنها في سياق مشترك مثل static أو global.

تستخدم لغات البرمجة، بدءًا من ALGOL و PL/I و C وصولًا إلى اللغات الحديثة، مكدس استدعاءات بشكل شبه دائم، وهو ما تدعمه عادةً مجموعات التعليمات لتوفير سجل تنشيط لكل استدعاء. وبهذه الطريقة، يمكن لاستدعاء متداخل تعديل متغيراته المحلية دون التأثير على أي من متغيرات الاستدعاء المعلق.

تتيح الاستدعاءات المتكررة تنفيذ الوظائف المحددة بواسطة الاستقراء الرياضي وخوارزميات فرق تسد المتكررة بشكل مباشر . إليك مثال على دالة متكررة بلغة C لإيجاد أعداد فيبوناتشي :

دالة فيبوناتشي ( عدد صحيح غير مُوقّع n ) { إذا كان ( n <= 1 ) { إرجاع n ؛ } إرجاع فيبوناتشي ( n - 1 ) + فيبوناتشي ( n - 2 }

لم تدعم لغات البرمجة المبكرة، مثل فورتران، الاستدعاء الذاتي في البداية، لأنه كان يتم تخصيص مجموعة واحدة فقط من المتغيرات وعنوان العودة لكل دالة قابلة للاستدعاء. [ 30 ] وقد صعّبت مجموعات تعليمات الحاسوب المبكرة تخزين عناوين العودة والمتغيرات على المكدس. أما الأجهزة المزودة بسجلات فهرسة أو سجلات للأغراض العامة ، مثل سلسلة CDC 6000 ، و PDP-6 ، وGE 635 ، و System/360 ، وسلسلة UNIVAC 1100 ، فكانت تستخدم أحد هذه السجلات كمؤشر للمكدس .

نطاق متداخل

تدعم بعض اللغات، مثل Ada و Pascal و PL/I و Python ، تعريف وتصريح دالة داخل جسم دالة، بحيث يكون اسم الدالة الداخلية مرئيًا فقط داخل جسم الدالة الخارجية.

مثال بسيط بلغة باسكال:

دالة E ( x : عدد حقيقي ) : عدد حقيقي ; دالة F ( y : عدد حقيقي ) : عدد حقيقي ; بداية F := x + y نهاية ; بداية E := F ( 3 ) + F ( 4 ) نهاية ;

الدالة Fمتداخلة داخل E. لاحظ أن Eمُعامل 's xمرئي أيضًا في F(لأنه Fجزء من E) بينما كل من xو yغير مرئيين خارج Eو Fعلى التوالي.

إعادة الدخول

إذا أمكن تنفيذ دالة قابلة للاستدعاء بشكل صحيح حتى أثناء تنفيذ دالة أخرى مماثلة، تُسمى هذه الدالة قابلة لإعادة الدخول . وتُعدّ الدوال القابلة لإعادة الدخول مفيدة أيضًا في بيئات متعددة الخيوط، حيث يمكن لعدة خيوط استدعاء الدالة نفسها دون خشية التداخل فيما بينها. في نظام معالجة المعاملات IBM CICS ، كان مصطلح "شبه قابلة لإعادة الدخول" شرطًا أقل تقييدًا، ولكنه مشابه، لبرامج التطبيقات التي تشترك فيها عدة خيوط.

التحميل الزائد

تدعم بعض لغات البرمجة التحميل الزائد ، مما يسمح باستدعاء دوال متعددة بنفس الاسم ضمن نفس النطاق، ولكنها تعمل على أنواع مختلفة من المدخلات. لنأخذ على سبيل المثال دالة الجذر التربيعي عند تطبيقها على مدخلات من الأعداد الحقيقية، والأعداد المركبة، والمصفوفات. تختلف خوارزمية كل نوع من المدخلات، وقد يكون نوع القيمة المُعادة مختلفًا. بكتابة ثلاث دوال منفصلة بنفس الاسم، مثل sqrt ، يصبح الكود الناتج أسهل في الكتابة والصيانة، لأن لكل دالة اسمًا يسهل فهمه وتذكره، بدلًا من استخدام أسماء أطول وأكثر تعقيدًا مثل sqrt_real و sqrt_complex و qrt_matrix .

يدعم العديد من اللغات التي تدعم الكتابة القوية خاصية التحميل الزائد . غالبًا ما يختار المترجم التحميل الزائد المطلوب استدعاؤه بناءً على نوع وسائط الإدخال، أو يفشل إذا لم تحدد وسائط الإدخال تحميلًا زائدًا. أما اللغات القديمة واللغات ذات الكتابة الضعيفة، فلا تدعم التحميل الزائد عمومًا.

فيما يلي مثال على التحميل الزائد في لغة C++ ، دالتان areaتقبلان أنواعًا مختلفة:

// تُعيد مساحة مستطيل مُحدد بالارتفاع والعرض double area ( double height , double width ) { return h * w ; }// تُعيد مساحة دائرة مُحددة بنصف قطرها double area ( double radius ) { return radius * radius * std :: numbers :: pi ; }int main () { double rectangleArea = area ( 3 , 4 ); double circleArea = area ( 5 ); }

تتيح لغة PL/I إمكانية GENERICتحديد اسم عام لمجموعة من مراجع الإدخال التي يتم استدعاؤها بأنواع مختلفة من الوسائط. مثال:

DECLARE gen_name GENERIC( الاسم عندما (ثنائي ثابت)، اللهب عندما (يطفو)، pathname otherwise);

يمكن تحديد تعريفات متعددة للوسائط لكل إدخال. سيؤدي استدعاء "gen_name" إلى استدعاء "name" عندما تكون الوسيطة من نوع FIXED BINARY، و"flame" عندما تكون من نوع FLOAT، وهكذا. إذا لم تتطابق الوسيطة مع أي من الخيارات، فسيتم استدعاء "pathname".

إنهاء

الدالة المغلقة هي دالة قابلة للاستدعاء، بالإضافة إلى قيم بعض متغيراتها المستمدة من البيئة التي أُنشئت فيها. كانت الدوال المغلقة سمة بارزة في لغة البرمجة ليسب، التي قدمها جون مكارثي . وبحسب طريقة التنفيذ، يمكن أن تُستخدم الدوال المغلقة كآلية للتأثيرات الجانبية.

الإبلاغ عن الاستثناءات

إلى جانب سلوك المسار السعيد ، قد يحتاج الكائن القابل للاستدعاء إلى إبلاغ المستدعي بحالة استثنائية حدثت أثناء تنفيذه.

تدعم معظم اللغات الحديثة الاستثناءات، مما يسمح بتدفق تحكم استثنائي يقوم بإزالة مكدس الاستدعاءات حتى يتم العثور على معالج استثناء للتعامل مع الحالة.

يمكن للغات التي لا تدعم الاستثناءات استخدام القيمة المُعادة للإشارة إلى نجاح أو فشل الاستدعاء. وثمة طريقة أخرى تتمثل في استخدام موقع معروف، مثل متغير عام، للإشارة إلى النجاح. حيث يقوم الكائن القابل للاستدعاء بكتابة القيمة، ويقرأها المستدعي بعد انتهاء الاستدعاء.

في نظام IBM System/360 ، حيث كان يُتوقع وجود رمز إرجاع من روتين فرعي، كان يُصمم رمز الإرجاع غالبًا ليكون من مضاعفات العدد 4، بحيث يمكن استخدامه كمؤشر مباشر لجدول التفرع، والذي غالبًا ما يكون موجودًا مباشرةً بعد تعليمة الاستدعاء لتجنب الاختبارات الشرطية الإضافية، مما يُحسّن الكفاءة بشكل أكبر. في لغة التجميع الخاصة بنظام System/360 ، يمكن كتابة ما يلي، على سبيل المثال:

 BAL 14، SUBRTN01 ينتقل إلى روتين فرعي، ويخزن عنوان الإرجاع في R14 B TABLE(15) استخدم القيمة المُعادة في السجل 15 لفهرسة جدول الفرع، * التفرع إلى الفرع المناسب instr. الجدول ب موافق، رمز الإرجاع = 00 جيد } B رمز الإرجاع BAD = 04 إدخال غير صالح } جدول الفروع B خطأ، رمز الإرجاع = 08، حالة غير متوقعة } 

اتصل برأس المال

تتضمن عملية الاستدعاء تكلفة إضافية أثناء التشغيل ، والتي قد تشمل على سبيل المثال لا الحصر:

  • تخصيص واستعادة مساحة تخزين مكدس الاستدعاءات
  • حفظ واستعادة سجلات المعالج
  • نسخ متغيرات الإدخال
  • نسخ القيم بعد الاستدعاء إلى سياق المُستدعي
  • الاختبار التلقائي لرمز الإرجاع
  • معالجة الاستثناءات
  • الإرسال، كما هو الحال بالنسبة للطريقة الافتراضية في لغة البرمجة الكائنية التوجه

تُستخدم تقنيات متنوعة لتقليل تكلفة وقت تشغيل المكالمات.

تحسين المُترجم

قد تبدو بعض التحسينات لتقليل تكلفة استدعاء الدوال بسيطة، لكن لا يمكن استخدامها إذا كان للدالة المستدعاة آثار جانبية. على سبيل المثال، في التعبير (f(x)-1)/(f(x)+1)، لا يمكن استدعاء الدالة fمرة واحدة فقط مع استخدام قيمتها مرتين، لأن الاستدعاءين قد يُرجعان نتائج مختلفة. علاوة على ذلك، في اللغات القليلة التي تُحدد ترتيب تقييم معاملات عامل القسمة، xيجب جلب قيمة المتغير مرة أخرى قبل الاستدعاء الثاني، لأن الاستدعاء الأول قد يكون غيّرها. يُعد تحديد ما إذا كان للدالة المستدعاة آثار جانبية أمرًا صعبًا ، بل غير قابل للحسم بموجب نظرية رايس . لذا، بينما يُعد هذا التحسين آمنًا في لغة برمجة وظيفية بحتة، يفترض مُصرّف لغة غير وظيفية عادةً أسوأ الحالات، وهي أن كل دالة مستدعاة قد يكون لها آثار جانبية.

التضمين

يُلغي تضمين التعليمات البرمجية استدعاءات الدوال القابلة للاستدعاء. إذ يستبدل المُصرّف كل استدعاء بالشيفرة المُصرّفة للدالة القابلة للاستدعاء. لا يقتصر الأمر على تجنب تكلفة الاستدعاء، بل يسمح للمُصرّف أيضًا بتحسين شيفرة الدالة المُستدعِية بشكل أكثر فعالية من خلال مراعاة السياق والوسائط في ذلك الاستدعاء. مع ذلك، عادةً ما يزيد تضمين التعليمات البرمجية من حجم الشيفرة المُصرّفة، إلا في حالة الاستدعاء مرة واحدة فقط أو عندما يكون نص الدالة قصيرًا جدًا، كسطر واحد.

مشاركة

يمكن تعريف الدوال القابلة للاستدعاء داخل البرنامج، أو بشكل منفصل في مكتبة يمكن استخدامها بواسطة برامج متعددة.

قابلية التشغيل البيني

يقوم المترجم بتحويل عبارات الاستدعاء والإرجاع إلى تعليمات الآلة وفقًا لاتفاقية استدعاء محددة . بالنسبة للتعليمات البرمجية التي يتم تجميعها بواسطة نفس المترجم أو مترجم متوافق، يمكن تجميع الدوال بشكل منفصل عن البرامج التي تستدعيها. تُسمى تسلسلات التعليمات المقابلة لعبارات الاستدعاء والإرجاع بمقدمة وخاتمة الإجراء .

الوظائف المدمجة

الدالة المدمجة ، أو الدالة المضمنة ، أو الدالة الجوهرية ، هي دالة يُولّد لها المُصرّف شيفرةً برمجيةً أثناء عملية الترجمة ، أو يُقدّمها بطريقةٍ تختلف عن الدوال الأخرى. [ 31 ] لا تحتاج الدالة المدمجة إلى تعريفٍ كغيرها من الدوال، لأنها مُدمجةٌ في لغة البرمجة. [ 32 ]

الدوال التي يتم تقييمها في وقت الترجمة

في بعض لغات البرمجة، مثل C++ و Rust و Zig ، يمكن تقييم الدوال في وقت الترجمة ؛ مما يقلل من الحمل الزائد في وقت التشغيل بطرق مثل عدم استخدام إطار مكدس إضافي ، واستخدام ذاكرة أقل، وتضمين قيم الإرجاع في الكود الثنائي نفسه. [ 33 ]

برمجة

المفاضلات

المزايا

تشمل مزايا تقسيم البرنامج إلى وظائف ما يلي:

  • تقسيم مهمة برمجة معقدة إلى خطوات أبسط: هذه إحدى الأداتين الرئيسيتين للبرمجة الهيكلية ، إلى جانب هياكل البيانات.
  • تقليل تكرار التعليمات البرمجية داخل البرنامج
  • تمكين إعادة استخدام التعليمات البرمجية عبر برامج متعددة
  • تقسيم مهمة برمجة كبيرة بين مبرمجين مختلفين أو مراحل مختلفة من المشروع
  • إخفاء تفاصيل التنفيذ عن مستخدمي الوظيفة
  • تحسين قابلية قراءة الكود عن طريق استبدال كتلة من التعليمات البرمجية باستدعاء دالة، حيث يُستخدم اسم الدالة لوصف كتلة التعليمات البرمجية. هذا يجعل التعليمات البرمجية المستدعِية موجزة وسهلة القراءة حتى لو لم يكن المقصود إعادة استخدام الدالة.
  • تحسين إمكانية التتبع (أي أن معظم لغات البرمجة توفر طرقًا للحصول على سجل استدعاء الدوال، والذي يتضمن أسماء الدوال المعنية، وربما معلومات إضافية مثل أسماء الملفات وأرقام الأسطر)؛ فعدم تقسيم الكود إلى دوال سيؤدي إلى إعاقة عملية تصحيح الأخطاء بشكل كبير.

العيوب

بالمقارنة مع استخدام التعليمات البرمجية المضمنة، فإن استدعاء دالة يفرض بعض العبء الحسابي في آلية الاستدعاء.

تتطلب الدالة عادةً رمزًا قياسيًا للصيانة - سواء عند الدخول إلى الدالة أو الخروج منها ( مقدمة الدالة وخاتمتها - وعادةً ما يتم حفظ سجلات الأغراض العامة وعنوان الإرجاع كحد أدنى).

الاتفاقيات

تم تطوير العديد من اصطلاحات البرمجة المتعلقة بالوظائف القابلة للاستدعاء.

فيما يتعلق بالتسمية، يقوم العديد من المطورين بتسمية الدالة القابلة للاستدعاء بعبارة تبدأ بفعل عندما تقوم بمهمة معينة، وبصفة عندما تقوم باستعلام، وباسم عندما يتم استخدامها لاستبدال المتغيرات.

يقترح بعض المبرمجين أن تؤدي الدالة القابلة للاستدعاء مهمة واحدة فقط، وإذا كانت تؤدي أكثر من مهمة، فيجب تقسيمها إلى دوال قابلة للاستدعاء متعددة. ويجادلون بأن الدوال القابلة للاستدعاء مكونات أساسية في صيانة البرمجيات ، ويجب أن تظل أدوارها في البرنامج متميزة.

يدعو أنصار البرمجة المعيارية إلى تقليل اعتماد كل دالة قابلة للاستدعاء على بقية قاعدة التعليمات البرمجية إلى أدنى حد . فعلى سبيل المثال، يُعتبر استخدام المتغيرات العامة غير مستحسن عمومًا، لأنه يُضيف ترابطًا بين جميع الدوال القابلة للاستدعاء التي تستخدم هذه المتغيرات. وإذا لم يكن هذا الترابط ضروريًا، فإنهم ينصحون بإعادة هيكلة الدوال القابلة للاستدعاء لقبول المعاملات المُمرَّرة .

أمثلة

لغة بيسك المبكرة

تتطلب الإصدارات الأولى من لغة BASIC أن يحمل كل سطر رقمًا فريدًا ( رقم السطر ) لترتيب الأسطر للتنفيذ، ولا توفر فصلًا بين أجزاء الكود القابلة للاستدعاء، ولا آلية لتمرير الوسائط أو إرجاع قيمة، وجميع المتغيرات عامة. يوفر الأمر `sub` اختصارًا لـ GOSUB` sub procedure` أو `subprocedure` أو `subroutine` . ينتقل التحكم إلى رقم السطر المحدد ثم يتابع إلى السطر التالي عند العودة.

10 REM A BASIC PROGRAM 20 GOSUB 100 30 GOTO 20 100 INPUT GIVE ME A NUMBER ; N 110 PRINT THE SQUARE ROOT OF ; N ; 120 PRINT IS ; SQRT ( N ) 130 RETURN

يطلب هذا الكود من المستخدم إدخال رقم بشكل متكرر، ثم يعرض الجذر التربيعي للقيمة. الأسطر من 100 إلى 130 هي الأسطر القابلة للاستدعاء.

Small Basic

في لغة مايكروسوفت سمول بيسك ، الموجهة للطلاب الذين يتعلمون البرمجة بلغة نصية، تُسمى الوحدة القابلة للاستدعاء روتينًا فرعيًا . Subتشير الكلمة المفتاحية إلى بداية الروتين الفرعي، ويليها مُعرِّف الاسم. أما الأسطر اللاحقة فهي جسم البرنامج الذي ينتهي بالكلمة EndSubالمفتاحية. [ 34 ]

Sub SayHello TextWindow . WriteLine ( "مرحبًا!" ) EndSub

يمكن تسمية هذا بـ SayHello()[ 35 ]

فيجوال بيسك

في الإصدارات اللاحقة من فيجوال بيسك (VB)، بما في ذلك أحدث إصداراتها و VB6 ، يُستخدم مصطلح " إجراء"Sub للإشارة إلى مفهوم الوحدة القابلة للاستدعاء. تُستخدم الكلمة المفتاحية `procedure` لإرجاع قيمة أو Functionعدم إرجاع أي قيمة. عند استخدامها في سياق فئة، يكون الإجراء بمثابة دالة. [ 36 ]

لكل معلمة نوع بيانات يمكن تحديده، ولكن إذا لم يكن كذلك، فسيتم استخدام النوع الافتراضي Objectللإصدارات اللاحقة المستندة إلى .NET ونوع متغير لـ VB6 . [ 37 ]

يدعم VB اصطلاحات تمرير المعاملات بالقيمة وبالمرجع باستخدام الكلمتين المفتاحيتين `value` و` reference` على التوالي. ما لم يتم تحديد `value`، يتم تمرير الوسيط `value` . لذلك، نادرًا ما يتم تحديد `value` بشكل صريح ByVal.ByRefByRefByValByVal

بالنسبة لنوع بيانات بسيط كالرقم، تكون هذه الاصطلاحات واضحة نسبيًا. ByRefيسمح تمرير قيمة إلى المتغير المُمرَّر للإجراء بتعديل المتغير المُمرَّر، بينما ByValلا يسمح تمرير قيمة إلى المتغير المُمرَّر بذلك. أما بالنسبة للكائنات، فقد تُربك الدلالات المبرمجين، إذ يُعامل الكائن دائمًا كمرجع. تمرير كائن ByValينسخ المرجع، وليس حالة الكائن. يمكن للإجراء المُستدعى تعديل حالة الكائن عبر توابعه، لكنه لا يستطيع تعديل مرجع الكائن الخاص بالمعامل الفعلي.

Sub DoSomething () ' بعض التعليمات البرمجية هنا End Sub

لا تُرجع هذه الدالة قيمة، ويجب استدعاؤها بشكل مستقل، مثلDoSomething

دالة GiveMeFive () كعدد صحيح GiveMeFive = 5 نهاية الدالة

هذا يُعيد القيمة 5، ويمكن أن يكون الاستدعاء جزءًا من تعبير مثلy = x + GiveMeFive()

Sub AddTwo ( ByRef intValue as Integer ) intValue = intValue + 2 End Sub

لهذا تأثير جانبي ، وهو تعديل المتغير المُمرر بالمرجع، ويمكن استخدامه لمتغير vمثل AddTwo(v). فمثلاً، إذا كانت قيمة v تساوي 5 قبل الاستدعاء، فستصبح 7 بعده.

لغة C ولغة C++

في لغتي C و C++ ، تُسمى الوحدة القابلة للاستدعاء دالة . يبدأ تعريف الدالة باسم نوع القيمة التي تُرجعها، أو voidيُشير إلى أنها لا تُرجع قيمة. يلي ذلك اسم الدالة، ثم الوسائط الرسمية بين قوسين، ثم أسطر جسم الدالة بين معقوفتين.

في لغة C++ ، تُسمى الدالة المُعلنة داخل فئة (كدالة غير ثابتة) دالة عضوية أو طريقة . أما الدالة المُعلنة خارج فئة، فيمكن تسميتها دالة حرة لتمييزها عن الدالة العضوية. [ 38 ]

void doSomething () { // بعض التعليمات البرمجية }

لا تُرجع هذه الدالة قيمة، ويتم استدعاؤها دائمًا بشكل مستقل، مثلdoSomething()

دالة `returnFive ( ) ` تُرجع 5 .

تُعيد هذه الدالة القيمة العددية 5. يمكن استدعاء الدالة بشكل مستقل أو ضمن تعبير مثلy = x + returnFive()

void addTwo ( int * pi ) { * pi += 2 ; }

لهذه الدالة تأثير جانبي ، فهي تُعدّل القيمة المُمرّرة بواسطة العنوان إلى قيمة الإدخال مضافًا إليها 2. يمكن استدعاؤها لمتغير vحيث addTwo(&v)تُشير علامة العطف (&) إلى المُصرّف بتمرير عنوان المتغير. فإذا كانت قيمة v هي 5 قبل الاستدعاء، فستصبح 7 بعده.

void addTwo ( int & i ) { i += 2 ; }

تتطلب هذه الدالة لغة C++ ، ولن تُترجم كلغة C. لها نفس سلوك المثال السابق، ولكنها تُمرر المعامل الفعلي بالمرجع بدلاً من تمرير عنوانه. addTwo(v)لا يتضمن استدعاء مثل هذا علامة العطف (&) لأن المُترجم يتعامل مع التمرير بالمرجع دون الحاجة إلى كتابة أي صيغة في الاستدعاء.

PL/I

في لغة PL/I ، يمكن تمرير مُعرِّف إلى إجراء مُستدعى ، يُقدِّم معلومات حول الوسيط، مثل أطوال السلاسل النصية وحدود المصفوفة. هذا يجعل الإجراء أكثر عمومية، ويُغني المبرمج عن تمرير هذه المعلومات. افتراضيًا، تُمرِّر PL/I الوسائط بالمرجع. قد تبدو دالة (بسيطة) لتغيير إشارة كل عنصر من عناصر مصفوفة ثنائية الأبعاد كما يلي:

تغيير_الإشارة : إجراء ( مصفوفة ) ؛ تعريف مصفوفة (*,*) عدد عشري ؛ مصفوفة = - مصفوفة ؛ نهاية تغيير_الإشارة ؛

يمكن استدعاء هذا باستخدام مصفوفات مختلفة كما يلي:

/* حدود المصفوفة الأولى من -5 إلى +10 ومن 3 إلى 9 */ declare array1 ( -5 : 10 , 3 : 9 ) float ; /* حدود المصفوفة الثانية من 1 إلى 16 ومن 1 إلى 16 */ declare array2 ( 16 , 16 ) float ; call change_sign ( array1 ) ; call change_sign ( array2 ) ;

بايثون

في لغة بايثون ، تشير الكلمة المفتاحية defإلى بداية تعريف الدالة. وتليها عبارات جسم الدالة مع مراعاة المسافة البادئة في الأسطر اللاحقة، وتنتهي عند السطر الذي يحمل نفس المسافة البادئة للسطر الأول أو نهاية الملف. [ 39 ]

دالة تنسيق_التحية ( الاسم : سلسلة نصية ) -> سلسلة نصية : تُرجع f "مرحباً، { الاسم } !"def greet_martin () -> None : print ( format_greeting ( "Martin" ))

تقوم الدالة الأولى بإرجاع نص ترحيبي يتضمن الاسم الذي يمرره المستدعي. أما الدالة الثانية فتستدعي الأولى، ويتم استدعاؤها كما لو greet_martin()كانت تكتب "مرحباً مارتن" في وحدة التحكم.

مقدمة

في التفسير الإجرائي للبرامج المنطقية ، تعمل الاستلزامات المنطقية كإجراءات لاختزال الهدف. قاعدة (أو بند ) على الشكل التالي:

A :- B

والتي لها القراءة المنطقية التالية:

A if B

يتصرف كإجراء يقلل الأهداف التي تتحد مع Aإلى أهداف فرعية تمثل حالات من B.

لنأخذ على سبيل المثال برنامج Prolog:

mother_child ( elizabeth , charles ). father_child ( charles , william ). father_child ( charles , harry ). parent_child ( X , Y ) :- mother_child ( X , Y ). parent_child ( X , Y ) :- father_child ( X , Y ).

لاحظ أن وظيفة الأمومة ممثلة بعلاقة، كما هو الحال في قاعدة البيانات العلائقية . ومع ذلك، تعمل العلاقات في لغة برولوج كوحدات قابلة للاستدعاء.X=mother(Y)

على سبيل المثال، ينتج عن استدعاء الإجراء المخرجات التالية . ولكن يمكن استدعاء الإجراء نفسه بأنماط إدخال وإخراج أخرى. على سبيل المثال:?-parent_child(X,charles)X=elizabeth

?- parent_child ( elizabeth , Y ). Y = charles .?- parent_child ( X , Y ). X = elizabeth , Y = charles .X = تشارلز ، Y = هاري .X = تشارلز ، Y = ويليام .?- parent_child ( william , harry ). no .?- parent_child ( elizabeth , charles ). yes .

انظر أيضاً

مراجع

  1. "مسرد المصطلحات" . nist.gov . المعهد الوطني للمعايير والتكنولوجيا . تم الاطلاع عليه في 9 فبراير 2024. الوحدة القابلة للاستدعاء: (في برنامج حاسوبي أو تصميم منطقي) دالة، أو طريقة، أو عملية، أو روتين فرعي، أو إجراء، أو وحدة هيكلية مماثلة تظهر داخل وحدة نمطية.
  2. دونالد إي. كنوث (1997). فن برمجة الحاسوب، المجلد الأول: الخوارزميات الأساسية . أديسون-ويسلي. ISBN 0-201-89683-4.
  3. أو. ج. دال؛ إي. دبليو. ديكسترا؛ سي. إيه. آر. هوار (1972). البرمجة الهيكلية . دار النشر الأكاديمية. ISBN 0-12-200550-3.
  4. "ما هو التجريد في البرمجة؟ شرح للمبتدئين" . freeCodeCamp.org . 21 ديسمبر 2022. تم الاطلاع عليه بتاريخ 25 نوفمبر 2025 .
  5. 1 2 ماوكلي، جيه دبليو (1982). "إعداد المسائل لآلات من نوع EDVAC" . في راندل، برايان (محرر). أصول الحواسيب الرقمية . سبرينغر. ص 393-397 . doi : 10.1007/978-3-642-61812-3_31 . ISBN  978-3-642-61814-7.
  6. ويلر، دي جيه (1952). "استخدام البرامج الفرعية في البرامج" (ملف PDF) . وقائع الاجتماع الوطني لجمعية ACM لعام 1952 (بيتسبرغ) - ACM '52 . ص 235. doi : 10.1145/609784.609816 . 
  7. ويلكس، إم في؛ ويلر، دي جيه؛ جيل، إس. (1951). إعداد البرامج للحاسوب الرقمي الإلكتروني . أديسون-ويسلي.
  8. داينيث، جون (2004). ""فتح روتين فرعي". قاموس الحوسبة . Encyclopedia.com . تم الاطلاع عليه بتاريخ 14 يناير 2013 .
  9. تورينج، آلان م. (1945)، تقرير الدكتور أ.م. تورينج حول مقترحات تطوير محرك الحوسبة الآلي (ACE): مقدم إلى اللجنة التنفيذية للمختبر الفيزيائي الوطني في فبراير 1946أُعيد طبعه في: كوبلاند، بي جيه ، محرر (2005). محرك الحوسبة الآلي لآلان تورينج . أكسفورد: مطبعة جامعة أكسفورد. ص 383. ISBN  0-19-856593-3.
  10. سبيسر، أمبروس بول (2002). "جهاز كونراد تسوز Z4: البنية والبرمجة والتعديلات في المعهد الفدرالي السويسري للتكنولوجيا في زيورخ". في روخاس، راؤول ؛ هاشاجن، أولف [بالألمانية] (محرران). الحواسيب الأولى: التاريخ والبنى . معهد ماساتشوستس للتكنولوجيا. الصفحات 263-276 . ISBN  978-0-262-18197-6.
  11. تورينج، آلان ماثيسون (19 مارس 1946) [1945]، مقترحات للتطوير في قسم الرياضيات لمحرك الحوسبة الآلي (ACE)(ملاحظة: تم تقديمها في 19-03-1946 أمام اللجنة التنفيذية للمختبر الفيزيائي الوطني (بريطانيا العظمى).)
  12. كاربنتر، برايان إدوارد ؛ دوران، روبرت ويليام (1 يناير 1977) [أكتوبر 1975]. "آلة تورينج الأخرى" . مجلة الكمبيوتر . 20 (3): 269-279 . doi : 10.1093/comjnl/20.3.269 .(11 صفحة)
  13. 1 2 إيزاكسون، والتر (18 سبتمبر 2014). "والتر إيزاكسون يتحدث عن نساء إينياك" . مجلة فورتشن . مؤرشف من الأصل في 12 ديسمبر 2018. تم الاطلاع عليه في 14 ديسمبر 2018 .
  14. هيرمان هـ. غولدستاين؛ جون فون نيومان (1947). "المجلد 3، 12.0 دمج الإجراءات" (ملف PDF) . تقرير عن الجوانب الرياضية والمنطقية لجهاز حاسوب إلكتروني - الجزء الثاني، المجلد 1-3، تخطيط وتشفير المسائل لجهاز حاسوب إلكتروني (ملف PDF) (تقرير فني). معهد الدراسات المتقدمة .
  15. الخصائص التشغيلية للمعالجات الخاصة بجهاز Burroughs B5000 (ملف PDF) . المراجعة أ. شركة Burroughs . 1963. 5000-21005 . تاريخ الاسترجاع: 8 فبراير 2024 .
  16. "تعليمات الضغط لأسفل" (ملف PDF) . معالج البيانات المبرمج 6 - دليل المستخدم (ملف PDF) . صفحة 37. تم الاطلاع عليه بتاريخ 8 فبراير 2024 . 
  17. غاي لويس ستيل الابن، مذكرة الذكاء الاصطناعي رقم 443. "دحض أسطورة "استدعاء الإجراء المكلف"؛ أو، تطبيقات استدعاء الإجراء التي تعتبر ضارة" . القسم "ج. لماذا تتمتع استدعاءات الإجراءات بسمعة سيئة".
  18. فرانك، توماس س. (1983). مقدمة إلى جهاز PDP-11 ولغة التجميع الخاصة به . سلسلة برامج برنتيس هول. برنتيس هول. ص 195. ISBN  9780134917047تم الاطلاع عليه بتاريخ 6 يوليو 2016. يمكننا تزويد موظف التجميع لدينا بنسخ من شفرة المصدر لجميع الإجراءات الفرعية المفيدة، ثم عند تقديم برنامج رئيسي للتجميع له، نخبره بالإجراءات الفرعية التي سيتم استدعاؤها في البرنامج الرئيسي [...]
  19. نظام الحاسوب العلمي متعدد الأغراض UNIVAC (الطراز 1103 A) - معلومات أولية (ملف PDF) . قسم أبحاث الهندسة في شركة ريمنجتون راند . 1 ديسمبر 1955. ص 1-10 . تاريخ الاطلاع: 8 أكتوبر 2025 . 
  20. "عمليات التحكم" (ملف PDF) . 704 آلة معالجة البيانات الإلكترونية - دليل التشغيل (ملف PDF) . شركة IBM . 1955. صفحة 25. 24-6661-2 . تم الاطلاع عليه بتاريخ 8 أكتوبر 2025 . 
  21. "التخزين التلقائي لمحتويات سجل P (STP)" (ملف PDF) . نظام معالجة البيانات الإلكترونية RCA 501 - دليل مرجعي للمبرمجين (ملف PDF) . قسم معالجة البيانات الإلكترونية في RCA . 1958. ص 18. P501-2 . تاريخ الاسترجاع: 8 أكتوبر 2025 . 
  22. "سجلات التاريخ" (ملف PDF) . نظام معالجة البيانات الترانزستوري Honeywell 800 - دليل مرجعي للمبرمجين (ملف PDF) . Honeywell . 1960. ص 55. DSI-31 . تم الاطلاع عليه بتاريخ 8 أكتوبر 2025 . 
  23. دليل برمجة الحاسوب الإلكتروني رويال بريسيجن LGP-30 . بورت تشيستر، نيويورك: رويال بريسيجن. أبريل 1957. تم الاطلاع عليه بتاريخ 19 نوفمبر 2023 .
  24. تانينباوم، أندرو س.؛ أوستن، تود (2013). تنظيم الحاسوب الهيكلي ( الطبعة السادسة). بوسطن: بيرسون. ISBN  978-0-13-291652-3.
  25. تانينباوم، أندرو س.؛ أوستن، تود (2013). تنظيم الحاسوب الهيكلي . التعلم المستمر ( الطبعة السادسة). بوسطن، ماساتشوستس. ميونيخ: بيرسون. ISBN  978-0-13-291652-3.
  26. بوتلر، ديك؛ فاريل، جاكلين؛ نيكولز، برادفورد (1996). برمجة PThreads: معيار POSIX لتحسين المعالجة المتعددة . دار نشر أورايلي ميديا، الصفحات 2-5 . ISBN  978-1-4493-6475-5. OCLC 1036778036 . 
  27. "مركز معلومات ARM" . Infocenter.arm.com . تم الاطلاع عليه بتاريخ 29 سبتمبر 2013 .
  28. "استخدام مكدس x64" . مايكروسوفت ليرن . مايكروسوفت. أنواع الدوال . تم الاسترجاع في 29 أكتوبر 2025 .
  29. مارتن، روبرت سي. (1 أغسطس 2008). الكود النظيف: دليل لحرفية تطوير البرمجيات الرشيقة ( الطبعة الأولى). بيرسون . ISBN  9780132350884تم الاطلاع عليه بتاريخ 19 مايو 2024 .
  30. فيرهوف، توم (2018). "درس متقدم في الاستدعاء الذاتي" . في: بوكنهاور، هانز-يواكيم؛ كوم، دينيس؛ أونغر، والتر (محررون). مغامرات بين الحدود الدنيا والارتفاعات العليا: مقالات مهداة إلى يوراي هرومكوفيتش بمناسبة عيد ميلاده الستين . سبرينغر. ص 616. ISBN  978-3-319-98355-4. OCLC 1050567095 . 
  31. "الوظائف المدمجة" . ibm.com . 9 مارس 2017. تم الاطلاع عليه بتاريخ 25 ديسمبر 2023 .
  32. مواد دراسية حول لغة بايثون . أبريل 2023. ص 87. تم الاطلاع عليها بتاريخ 25 ديسمبر 2023 . 
  33. مايكروسوفت ليرن (22 فبراير 2023). "constexpr (C++)" . learn.microsoft.com . مايكروسوفت ليرن.
  34. "Small Basic" . Small Basic . تم الاسترجاع في 8 فبراير 2024 .
  35. "دليل البدء السريع لبرنامج Small Basic: الفصل 9: الإجراءات الفرعية" . مايكروسوفت. 17 يناير 2024.
  36. "الإجراءات في فيجوال بيسك" . مايكروسوفت ليرن . 15 سبتمبر 2021. تم الاطلاع عليه بتاريخ 8 فبراير 2024 .
  37. "عبارة Dim (Visual Basic)" . Microsoft Learn . 15 سبتمبر 2021. تم الاطلاع عليه بتاريخ 8 فبراير 2024 .
  38. "ما المقصود بالدالة الحرة" ؟
  39. "4. المزيد من أدوات التحكم في التدفق — وثائق بايثون 3.9.7" .