المسارات
/
Elixir
Elixir
/
التمارين
/
الطفح السفلي للمكدس
الطفح السفلي للمكدس

الطفح السفلي للمكدس

تمرين تعلّمي

مقدمة

الاستثناءات

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

  • اسم الوحدة يحدّد اسم الخطأ.
  • الوحدة تعرّف بنية الخطأ.
  • ستحتوي البنية على حقل :message.
  • يمكن استخدام الوحدة مع raise/1 وraise/2 لرفع الخطأ المقصود

يحدّد سلوك الاستثناء أيضًا دالتَي استدعاء راجعتين: message/1 وexception/1. وإذا لم تُنفَّذ، ستُستخدم تنفيذات افتراضية. تحوّل message/1 بنية الخطأ إلى رسالة مقروءة عند استدعائها مع raise. وتتيح exception/1 إضافة سياق إضافي إلى الرسالة عند استدعائها مع raise/2.

تعريف استثناء

لتعريف استثناء انطلاقًا من وحدة خطأ، نستخدم ماكرو defexception:

# Defines a minimal error, with the name `MyError`
defmodule MyError do
  defexception message: "error"
end

# Defines an error with a customized exception/1 function
defmodule MyCustomizedError do
  defexception message: "custom error"

  @impl true
  def exception(value) do
    case value do
      [] ->
        %MyCustomizedError{}

      _ ->
        %MyCustomizedError{message: "Alert: " <> value}
    end
  end
end

استخدام الاستثناءات

يمكن استخدام الأخطاء المعرّفة مثل خطأ مدمج باستخدام raise/1 أو raise/2.

  • raise/1 يرفع خطأً محددًا باسم وحدته، وإذا كان الوسيط سلسلة نصية، فإنه يرفع RuntimeError وتكون هذه السلسلة النصية هي رسالته.
  • raise/2 يرفع خطأً محددًا باسم وحدته، ويقبل وسيط سمات يُستخدم للحصول على الخطأ بالرسالة المناسبة.

التعليمات

بينما تواصل عملك في Instruments of Texas، هناك تقدم يُحرز في تنفيذ Elixir لآلة حاسبة RPN. يرغب فريقك في أن يكون قادرًا على رفع أخطاء أكثر تحديدًا من الأخطاء العامة التي توفرها المكتبة القياسية. أنت تجري بعض البحث، لكنك قررت تنفيذ خطأين جديدين يطبقان سلوك الاستثناء.

1. خطأ القسمة على صفر

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

نفّذ الوحدة DivisionByZeroError لتحتوي على رسالة الخطأ: "division by zero occurred"

raise DivisionByZeroError
# => ** (DivisionByZeroError) division by zero occurred

2. خطأ عند مواجهة نقص المكدس

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

raise StackUnderflowError
# => ** (StackUnderflowError) stack underflow occurred

raise StackUnderflowError, "when dividing"
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing

3. اكتب دالة قسمة

نفّذ الدالة divide/1 التي تأخذ مكدسًا (مصفوفة من عددين) وتقوم بما يلي:

  • ترفع نقص المكدس عندما لا يحتوي المكدس على أعداد كافية
  • ترفع القسمة على صفر عندما يكون المقسوم عليه 0 (لاحظ أن مصفوفة الأعداد مخزنة بترتيب معكوس)
  • تنفذ القسمة عندما لا تُرفع أخطاء
RPNCalculator.Exception.divide([])
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing

RPNCalculator.Exception.divide([0, 100])
# => ** (DivisionByZeroError) division by zero occurred

RPNCalculator.Exception.divide([4, 16])
# => 4

لاحظ أن ترتيب المصفوفة معكوس!

تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Elixir Exercism

مستعد لبدء الطفح السفلي للمكدس؟

سجّل في Exercism لتتعلّم وتتقن Elixir عبر 58 مفهومًا168 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.