الجراءات والدوال والبرمجة المهيكلة
| English | العربية |
|---|---|
| subroutines/ˈsʌbruːtiːnz/ | إجراءات جزئية |
| function/ˈfʌŋkʃn/ | دالة |
| procedure/prəˈsiːdʒə/ | إجراء |
| structured programming/ˈstrʌktʃəd ˈprəʊɡræmɪŋ/ | البرمجة المنسقة |
| decomposition/ˌdiːkɒmpəˈzɪʃn/ | تحلل |
| parameters/pəˈræmɪtəz/ | المعاملات |
| arguments/ˈɑːɡjuːmənts/ | وسائط |
| signature/ˈsɪɡnɪtʃə/ | التوقيع |
| pass by value/pæs baɪ ˈvæljuː/ | التمرير بالقيمة |
| pass by reference/pæs baɪ ˈrefrəns/ | التمرير بالإشارة |
| global variable/ˈɡləʊbl ˈveərɪəbl/ | متغير عالمي |
| local variable/ˈləʊkl ˈveərɪəbl/ | متغير محلي |
| scope/skəʊp/ | نطاق |
شريط من الروتين يمكن لأي شخص استعارته
- بحلول عام 1951، احتفظ فريق EDSAC في كامبل بمكتبة من الرتبات الفرعية على شريط ورق مثقب: جذور تربيعية، الطباعة، اللوغاريتمات. أي برنامج يمكنه قراءتها واستدعاؤها.
- الجزء الصعب كان العودة. خدعة ديفيد وييلر، "القفزة الويلرية"، حفظت عنوان العودة بحيث يمكن للرتبة الفرعية العودة إلى أي مكان تم استدعاؤها منه.
- كل استدعاء دالة تكتبه اليوم يفعل نفس الشيء، ومكتبة كل لغة تنحدر من ذلك الشريط.
- هذه الدرس هي الإجراءات والدوال: كيفية تعريفها، كيفية تمرير القيم بداخلها وخارجها، وكيفية كتابة واحدة كما ترسمها ورقة 2.
إجراءات ودوال
- البرمجة المنظمة تبني برنامجًا من رتبات فرعية صغيرة ذات أسماء، كل منها مهمة واحدة.
- الإجراء هو كتلة مسماة تقوم بإجراء عمل ولا تُرجع شيئًا:
PROCEDURE Greet(Name : STRING) … ENDPROCEDURE، يتم تشغيلها بـCALL Greet("Ada"). - الدالة تُرجع قيمة تصبح جزءًا من تعبير:
FUNCTION Square(X : INTEGER) RETURNS INTEGER … RETURN X * X … ENDFUNCTION، تُستخدم كـResult ← Square(5) + 1.

الإجراء يقوم بشيء ما؛ الدالة تُرجع قيمة
مكدس الاستدعاء: دفع عند الاستدعاء، سحب عند الإرجاع
استدعاء الدالة الفرعية يضيف إطاراً جديداً في الأعلى؛ والإرجاع يحذفه ويعيد قيمة إلى المُنشئ. الإجراء الجاري تشغيله هو دائماً الإطار الموجود في الأعلى.
الفرق الجوهري بين الإجراء والدالة هو أن الدالة:
الدالة ترجع قيمة (تُستخدم في تعبير)؛ بينما الإجراء يقوم بعمل ولا ترجع شيئاً.
الدالة Square(x) ترجع x * x. ماذا تُرجع الاستدعاء Square(5)؟
5 × 5 = 25 — القيمة التي تُرسلها الدالة إلى مُنشئها (الإطار الذي يُحذف من كومة الاستدعاءات).
أين يكون كل منهما مناسبًا
- الإجراء عندما تكون نفس المجموعة من الخطوات مطلوبة في عدة نقاط: التحقق من مدخلات، عرض قائمة، تبديل قيمتين. تُكتب الخطوات مرة واحدة وتُستدعى بالاسم.
- الدالة عندما يجب حساب قيمة واحدة ثم استخدامها في تعبير: مجموع، نتيجة
TRUE/FALSE، الأكبر بين عددين. تحل القيمة المُرجعة محل الاستدعاء. - استخدم subroutine (الجزء الفرعي) عندما يظهر المنطق في أكثر من مكان، عندما يكون للكتلة غرض مسماو واضح، عندما يكون البرنامج معقدًا بما يكفي ليدعم التفكيك، أو عندما تريد اختبار جزء منه بشكل مستقل.
سبب جيد لكتابة دالة فرعية هو أن:
تزيل الدوال الفرعية التكرار، وتوفر غرضاً مسمّى، ويمكن اختبارها بشكل مستقل.
المعاملات، الحجاج والواجهة
- المعاملات هي المتغيرات التي يعلنها الجزء الفرعي لاستقبال القيم؛ القيم التي يوفرها المCALLER تسمى الحجاج.
- الرأس هو السطر الأول:
PROCEDURE Name(Param : TYPE)أوFUNCTION Name(Param : TYPE) RETURNS TYPE. الواجهة، أو التوقيع، هي الاسم، المعاملات بالترتيب مع أنواعها، ونوع الإرجاع: كل ما يحتاجه المCALLER معرفته. - القيمة المُرجعة هي ما تُرسله الدالة مع
RETURN.
صل كل مصطلح بما يعنيه.
الدالة مقابل الإجراء = إرجاع قيمة أم لا؛ بالقيمة مقابل بالمرجع = نسخة أم أصل.
مثال محلول: وصف كل حد في الرأس
FUNCTION Pass2(Count : INTEGER) RETURNS BOOLEAN.FUNCTION: جزء فرعي يُرجع قيمة.Pass2: المعرّف المستخدم لاستدعائه.Count: المعامل، المعرّف الذي يستقبل الحجة الممررة.INTEGER: نوع البيانات لهذا المعامل.RETURNS BOOLEAN: نوع بيانات القيمة التي تُرجعها الدالة. خمسة أجزاء، علامة لكل جزء.
في FUNCTION Pass2(Count : INTEGER) RETURNS BOOLEAN، المعرف Count هو الـ ____.
المعامل يستقبل الحُجْجة التي يُمررها المُنشئ ويُستخدم داخل الدالة مثل المتغير المحلي.
التمرير بالقيمة والتمرير بالإشارة
- التمرير بالقيمة: يتلقى الروتينة نسخة، لذا فإن التغييرات داخله لا تصل إلى المCALLER. استخدمه للمدخلات التي تقرأها الروتينة فقط.
- التمرير بالإشارة: يتلقى الروتينية إشارة إلى متغير المCALLER الخاص بها، لذا فإن التغييرات تصل إلى المCALLER. استخدمه عندما يجب على الروتينة تحديث الحجة، كما في
Swap. - كامبريدج تكتب الوضع في الرأس،
BYVALأوBYREF، قبل كل معامل. إذا لم يُكتب أي منهما، يُفترضBYVAL.

نسخة، أو رابط لمتغير المCALLer
مثال محلول: ما هو المخرجات؟
PROCEDURE Adjust(BYREF X : INTEGER, BYVAL Y : INTEGER)
X <- X + Y
Y <- Y * 2
ENDPROCEDURE
A <- 5
B <- 3
CALL Adjust(A, B)
OUTPUT A, B
Xهو إشارة إلىA، لذا يصبحAيساوي 8.Yهي نسخة منB، لذا فإن مضاعفةYتتركBعند 3.- المخرجات هي
8, 3. لو كان الرأس يقولBYVAL X، لكانAلا يزال 5.
في المثال المحلول، ما هي قيمة A بعد CALL Adjust(A, B)؟
X يتم تمريره BYREF، لذا يضيف X ← X + Y 3 إلى A الخاصة بالمُنشئ: 5 + 3 = 8. B تبقى 3 لأن Y كانت نسخة.
المتغيرات المحلية والعالمية
- المتغير المحلي يُعلن داخل جزء فرعي ويوجد فقط أثناء تشغيله؛ المتغير العالمي يُعلن خارج ويتاح في كل مكان. المنطقة التي يكون فيها الاسم متاحًا تسمى النطاق.
- المحليات مفضلة: يمكن إعادة استخدام نفس المعرّف في أماكن أخرى دون تصادم، لا يمكن تغيير قيمته عن طريق الخطأ بواسطة أجزاء أخرى من البرنامج، يتم تحرير الذاكرة عند الإرجاع، ويكون الجزء الفرعي مستقلًا ذاتيًا.
- يتم إنشاء محلي جديد في كل استدعاء، لذا لا يمكنه حمل قيمة بين الاستدعاءات. روتين يبني سلسلة نصية عبر استدعاءات متكررة يحتاج إلى أن تكون تلك السلسلة عالمية، أو تُمرر
BYREF.

العالمي متاح في كل مكان؛ المحلي يعيش فقط داخل جزء فرعي خاص به
المتغير المحلي موجود فقط داخل الدالة الفرعية التي تم الإعلان عنها فيها، بينما المتغير العالمي مرئي في كل مكان في البرنامج.
إبقاء المتغيرات محلية يحد من نطاقها، ويتجنب تصادم الأسماء، ويجعل الدالة الفرعية قابلة للاختبار بمفردها — وتجنب المتغيرات العالمية هو الأفضل.
ما هي فوائد استخدام المتغيرات المحلية؟ حدد كل الخيارات الصحيحة.
يتم إنشاء متغير محلي جديد في كل استدعاء، لذا لا يمكنه الاحتفاظ بقيمة بين الاستدعاءات. هذه هي الوظيفة الوحيدة التي يؤديها المتغير العالمي أو معامل BYREF بدلاً منه.
تحويل إجراء إلى دالة
- غير
PROCEDUREإلىFUNCTIONوأضفRETURNS <type>إلى الرأس. - استبدل
OUTPUT، أوBYREFالمعامل الذي حمل النتيجة للخارج، بعبارةRETURN. - غيّر كل استدعاء بحيث تُستخدم القيمة المُرجعة:
Result ← Unpack(Text)بدلاً منCALL Unpack(Text, Result).
لتحويل إجراء إلى دالة، غيّر الترويسة لتصبح FUNCTION مع RETURNS، واستبدل OUTPUT بـ RETURN، وغيّر الاستدعاءات لاستخدام القيمة المرجعة.
ثلاثة تغييرات، ثلاث درجات: الترويسة، وRETURN، والاستدعاءات.
مثال محلول: كتابة وحدة لورقة العمل 2
- مصفوفة عالمية
Score : ARRAY[1:50] OF INTEGERتحتفظ بدرجات الاختبار. اكتب دالةCountAbove(Limit : INTEGER)تُرجع عدد الدرجات الأكبر منLimit.
FUNCTION CountAbove(BYVAL Limit : INTEGER) RETURNS INTEGER
DECLARE Index, Count : INTEGER
Count <- 0
FOR Index <- 1 TO 50
IF Score[Index] > Limit THEN
Count <- Count + 1
ENDIF
NEXT Index
RETURN Count
ENDFUNCTION
- يمنح النظام علامة لكل ميزة: الرأس مع المعامل ونوع الإرجاع، Declarations المحلية، عداد مُهيأ قبل الحلقة، حلقة تمر على كل عنصر، الشرط بمقارنة صحيحة، التحديث بداخله، إغلاق البناءات، و
RETURNواحد بعد الحلقة. - الوحدة غير المكتملة لا تزال تحصل على علامات لكل جزء صحيح، لذا اكتب الكل.

كل جزء من إجابة الوحدة يحمل علامته الخاصة
ضع أجزاء إجابة وحدة Paper 2 بالترتيب الذي تُكتب فيه.
ترويسة، إعلان، حلقة، شرط، تحديث، إرجاع. كل جزء يمثل درجة، حتى لو كان جزء آخر خاطئاً.
علامات ضائعة
- روتين يجب أن يغير متغير المCALLer يحتاج إلى
BYREFفي رأسه؛ بدونها يُفترضBYVALويضيع التغيير. - للدالة
RETURNواحدة، بعد الحلقة، وENDFUNCTION.RETURNداخل الحلقة ينهائها عند العنصر الأول. DECLAREكل متغير محلي، وابدأ عدادًا أو مجموعًا بـ 0 قبل بدء الحلقة.- "Pseudocode فعال" يعني نقل الأعمال التي لا تتغير خارج الحلقة، إيقاف البحث عند أول تطابق، وعدم تكرار استدعاء يمكن تخزين نتيجته.
لجعل الحلقة أكثر كفاءة، يجب أن تكون القيمة التي لا تتغير مع عداد الحلقة:
رفع المستقر خارج الحلقة يتجنب إعادة حساب نفس القيمة في كل تكرار.
لقد فهمت الأمر
- الإجراء يقوم بإجراء وهو
CALLed؛ الدالة تُرجع قيمة تُستخدم في تعبير - الرأس يسمي الروتينة، معاملاتها بأنواعها ونوع الإرجاع؛ الحجاج هي القيم الممررة
- BYVAL يمرر نسخة (الافتراضي)؛ BYREF يسمح للروتينة بتغيير متغير المCALLer
- يفضل المحلية المتغيرات؛ المحلي جديد في كل استدعاء، العالمي يحتفظ بقيمته
- وحدة في ورقة 2: الترويسة، التصريحات، التهيئة، الحلقة، الشرط، التحديث، البنى المغلقة، واحد
RETURN