def factorial(n: int) -> int:
# Recursive case
if n > 0:
recursive_result = factorial(n - 1)
return n * recursive_result
# Terminal case
return 1
factorial(5)
120
الفعل المتسلسل: يحتوي على جملة يطلب فيها نفسه. ويجب أن تؤول سلسلة الطلبات هذه إلى جملة تنهي التسلسل.
تنبيه: هذا مبحثٌ شيِّق، وقد يكون فيه شيءٌ من الصعوبة، لكنّ فيه أدوات فعَّالة في استعمال المنطق البرمجي بأقصى مدى.
فمثلا: تعرف الرياضيات مضروب العدد
\[ !n = n(n-1)(n-2)\cdots(1) \]
فهي عملية ضرب لكل عدد مع الذي قبله حتى ينتهي للواحد. ومن أمثلته:
\[ !5 = (5)(4)(3)(2)(1) \]
ولك أن تصف نفس العملية هكذا:
\[ !n = n !(n-1) \]
أي أن مضروب العدد هو ضربُ هذا العدد في مضروب العدد الذي قبله. وذلك يتسلسل على النحو التالي:
\[ !5 = (5)!(4) = (5)(4!(3)) = (5)(4(3!(2))) = (5)(4(3(2!(1)))) = (5)(4(3(2(1)))) = (5)(4)(3)(2)(1) \]
إذا نخلص بالمعادلة التالية:
\[ !n = n(n-1)(n-2)\cdots(1) = n!(n-1) \]
وهكذا يكون تعريفها في بايثون:
def factorial(n: int) -> int:
# Recursive case
if n > 0:
recursive_result = factorial(n - 1)
return n * recursive_result
# Terminal case
return 1
factorial(5)
120
حيث لدينا حالتان:
n > 0
يتم الطلب الذاتي : recursive_result = factorial(n - 1)
إذْ هي جملة متسلسلة تكدِّس طلبات فوق طلبات؛ لكنها تؤول في النهاية إلى الجملة التي تُنهي التسلسلreturn 1
هي الجملة التي تنهي التسلسلوهنا قطعة كود نستعملها لتصور تسلسل الطلبات:
def factorial(n: int, depth: int = 0) -> int:
# Recursive case
print(f"{' ' * depth}Call factorial({n})")
if n > 0:
result = n * factorial(n - 1, depth + 1)
print(f"{' ' * depth}Return {result} from factorial({n})")
return result
# Terminal case
print(f"{' ' * depth}Return 1 from factorial({n})")
return 1
factorial(5)
Call factorial(5)
Call factorial(4)
Call factorial(3)
Call factorial(2)
Call factorial(1)
Call factorial(0)
Return 1 from factorial(0)
Return 1 from factorial(1)
Return 2 from factorial(2)
Return 6 from factorial(3)
Return 24 from factorial(4)
Return 120 from factorial(5)
120
n
هي المعيَّنة له وقت النداء.factorial(0)
الذي يؤول لنتيجة مباشرة: return 1
فيخلَّى هذا الظرف من الذاكرة وتعود نتيجته إلى الظرف المباشر الذي استدعاه وهو ظرف factorial(1)
.recursive_result = 1
وينتقل إلى الجملة التي بعدها وهي جملة الرجوع بنتيجة return n * recursive_result
وهُما معيَّنان، أي تكون الجملة في واقع الظرف: return 1 * 1
.factorial(2)
… إلخ.طلب الفعل المتسلسل يؤدي إلى ظروف متداخلة تؤول إلى ظرف واحد في النهاية.
يستعمل الفعل المتسلسل وكذلك هياكل البيانات المتسلسلة بشكل كبير في الخوارزميات الفعالة.
يسهل كتابة بعض الخوارزميات باستعمال الفعل المتسلسل. لكن قد تكون (أحياًنا) أقل أداءً من استعمال الحلقات.