Rutas
/
Elixir
Elixir
/
Ejercicios
/
Desbordamiento inferior de pila
Desbordamiento inferior de pila

Desbordamiento inferior de pila

Ejercicio de aprendizaje

Introducción

Excepciones

Todos los errores de Elixir implementan el Exception Behaviour. Igual que el Access Behaviour, el Exception Behaviour define funciones de callback que un módulo debe implementar para cumplir el contrato de software del behaviour. Una vez que se define un error, este tiene las siguientes propiedades:

  • El nombre del módulo define el nombre del error.
  • El módulo define un struct de error.
  • El struct tendrá un campo :message.
  • El módulo se puede usar con raise/1 y raise/2 para lanzar el error deseado

El Exception Behaviour también especifica dos callbacks: message/1 y exception/1. Si no se implementan, se usarán las implementaciones por defecto. message/1 transforma el struct de error en un mensaje legible cuando se llama con raise. exception/1 permite añadir contexto adicional al mensaje cuando se llama con raise/2

Definir una excepción

Para definir una excepción a partir de un módulo de error, usamos la macro 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

Usar las excepciones

Los errores definidos se pueden usar como un error integrado, con raise/1 o raise/2.

  • raise/1 lanza un error concreto por el nombre de su módulo o, si el argumento es un string, lanzará un RuntimeError con el string como mensaje.
  • raise/2 lanza un error concreto por el nombre de su módulo y acepta un argumento de atributos que se usa para obtener el error con el mensaje adecuado.

Instrucciones

Mientras continúas tu trabajo en Instruments of Texas, se están haciendo progresos en la implementación en Elixir de la calculadora RPN. A tu equipo le gustaría poder lanzar errores más específicos que los genéricos que proporciona la biblioteca estándar. Estás investigando un poco, pero has decidido implementar dos errores nuevos que implementan el comportamiento Exception.

1. Error al dividir entre cero

Dividir un número entre cero produce un resultado no definido, que el equipo decide que es mejor representar con un error.

Implementa el módulo DivisionByZeroError para que tenga el mensaje de error: "division by zero occurred"

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

2. Error al encontrarse con un subdesbordamiento de pila

Las calculadoras RPN usan una pila para llevar la cuenta de los números antes de sumarlos. El equipo representa esta pila con una lista de números (enteros y de coma flotante), por ejemplo: [3, 4.0]. Cada operación necesita una cantidad concreta de números en la pila para poder realizar su cálculo. Cuando no hay suficientes números en la pila, se habla de un error de subdesbordamiento de pila. Implementa la excepción StackUnderflowError, que proporciona un mensaje por defecto y un contexto adicional opcional

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

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

3. Escribe una función que divida

Implementa la función divide/1, que recibe una pila (una lista de dos números) y:

  • lanza un subdesbordamiento de pila cuando la pila no contiene suficientes números
  • lanza una división entre cero cuando el divisor es 0 (fíjate en que la pila de números se almacena en orden inverso)
  • realiza la división cuando no se lanza ningún error
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

¡Fíjate en que el orden de la lista está invertido!

Editar en GitHub El enlace se abre en una ventana o pestaña nueva
Elixir Exercism

¿Listo para empezar Desbordamiento inferior de pila?

Regístrate en Exercism para aprender y dominar Elixir con 58 conceptos168 ejercicios y mentoría humana real, todo gratis.