المسارات
/
Elixir
Elixir
/
المنهج
/
الاستدعاء الذاتي
ال

الاستدعاء الذاتي في Elixir

56 تمرينًا

نبذة عن الاستدعاء الذاتي

الدوال العودية هي دوال تستدعي نفسها.

تحتاج الدالة العودية إلى حالة أساسية واحدة على الأقل وإلى حالة عودية واحدة على الأقل.

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

في كثير من الأحيان، تُكتب كل حالة في فرع مستقل من الدالة.

# base case
def count([]), do: 0

# recursive case
def count([_head | tail]), do: 1 + count(tail)

يمكن أن تحتوي الدالة العودية على حالات أساسية كثيرة و/أو حالات عودية كثيرة. على سبيل المثال، متتالية فيبوناتشي متتالية عودية لها حالتان أساسيتان:

def fibonacci(0), do: 0
def fibonacci(1), do: 1
def fibonacci(n), do: fibonacci(n - 1) + fibonacci(n - 2)

وعدّ مرات ظهور قيمة معينة x في مصفوفة له حالتان عوديتان:

def count_occurrences([], _x), do: 0
def count_occurrences([x | tail], x), do: 1 + count_occurrences(tail, x)
def count_occurrences([_ | tail], x), do: count_occurrences(tail, x)

الحلقات من خلال الاستدعاء الذاتي

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

for(i = 0; i < array.size; i++) {
  # do something with array[i]
}

في لغة دالية، لا يمكن تغيير قيمة i (باستدعاء i++). لذلك يجب تنفيذ الحلقات باستخدام الاستدعاء الذاتي.

والمكافئ لحلقة for في Elixir يبدو هكذا:

def loop([]), do: nil

def loop([head | tail]) do
  do_something(head)
  loop(tail)
end

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

التنفيذ اللانهائي

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

ويمكن أن تنتج مشكلة التنفيذ اللانهائي هذه عن:

  • نسيان تنفيذ حالة أساسية.
  • عدم تعريف الحالة الأساسية في الفرع الأول.
  • عدم تعديل الوسيط بالشكل الصحيح عند إجراء الاستدعاء العودي، وبالتالي عدم الوصول إلى الحالة الأساسية أبدًا.
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم الاستدعاء الذاتي

التدريب مقفل

افتح 10 تمارين إضافية لممارسة الاستدعاء الذاتي