الدوال العودية هي دوال تستدعي نفسها.
تحتاج الدالة العودية إلى حالة أساسية واحدة على الأقل وإلى حالة عودية واحدة على الأقل.
تُرجع الحالة الأساسية قيمة دون استدعاء الدالة مرة أخرى. أما الحالة العودية فتستدعي الدالة مرة أخرى مع تعديل المدخل بحيث يطابق الحالة الأساسية في مرحلة ما.
إليك مثالًا يعدّ عناصر مصفوفة.
def count:
if length == 0 then
0 # base case
else
1 + (.[1:] | count) # recursive case
end;
([] | count), # => 0
([11, 22, 33] | count) # => 3
يمكن أن تحتوي الدالة العودية على عدة حالات أساسية و/أو عدة حالات عودية. على سبيل المثال، متتالية فيبوناتشي متتالية عودية لها حالتان أساسيتان.
def fibonacci:
if . == 0 then
0
elif . == 1 then
1
else
(. - 1 | fibonacci) + (. - 2 | fibonacci)
end;
10 | fibonacci # => 55
وعدّ عدد مرات ظهور قيمة معطاة x في مصفوفة له حالتان عوديتان.
def count_occurrences(x):
if length == 0 then
0
elif first == x then
1 + (.[1:] | count_occurrences(x))
else
(.[1:] | count_occurrences(x))
end;
[11, 22, 33, 22, 44] | count_occurrences(22) # => 2
عمليًا، غالبًا ما يتم التكرار على المصفوفات وغيرها من بُنى البيانات القابلة للتعداد باستخدام دوال مدمجة،
مثل map وreduce، أو باستخدام التدفقات مثل [.[] | select(...)].
وفي الخلفية، تُنفَّذ بعض الدوال المدمجة باستخدام العودية.
لقد انضممت للتو إلى فريق يحافظ على خط أنابيب بيانات مبني على jq.
وخلال أول جلسة برمجة ثنائية لك، يبدأ زميلك الجديد في التساؤل بفضول:
«هل تعرف كيف تعمل add وreverse وmap من الداخل؟ لنستكشف الأمر: جرّب أن تنفّذها بنفسك باستخدام العودية، ومن دون الدوال المدمجة.»
سنعيد تنفيذ المرشّح المدمج add للتدرب على العودية.
الحالة الأساسية هي أن مجموع مصفوفة فارغة يساوي صفر.
نفّذها بنفسك بدالة عودية، ولا تستخدم add المدمج.
[5, 4, 6, 10] | array_add # => 25
سنعيد تنفيذ المرشّح المدمج reverse.
الحالة الأساسية هي أن المصفوفة الفارغة إذا عُكس ترتيبها تبقى مصفوفة فارغة.
نفّذها بنفسك بدالة عودية، ولا تستخدم reverse المدمج.
[5, 4, 6, 10] | array_reverse # => [10, 6, 4, 5]
سنعيد تنفيذ المرشّح المدمج map.
تستقبل الدالة مرشّحًا كمعامل، وتُشغّل هذا المرشّح على كل عنصر من عناصر مصفوفة الإدخال، وتُرجع القيم الناتجة في مصفوفة جديدة.
الحالة الأساسية هي أن المصفوفة الفارغة تُنتج مصفوفة فارغة.
نفّذها بنفسك بدالة عودية، ولا تستخدم map المدمج.
[5, 4, 6, 10] | array_map(. + 10) # => [15, 14, 16, 20]
سجّل في Exercism لتتعلّم وتتقن jq عبر 12 مفهومًا75 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.