Tracks
/
Elixir
Elixir
/
Ejercicios
/
Calculadora RPN
Calculadora RPN

Calculadora RPN

Ejercicio de aprendizaje

Introducción

Errores

Los errores ocurren. En Elixir, aunque se suele decir «let it crash», hay ocasiones en las que necesitamos rescatar la llamada a la función hasta un estado válido conocido para cumplir con un contrato de software. En algunos lenguajes, los errores se usan como método de control de flujo, pero en Elixir este patrón no se recomienda. A menudo podemos reconocer las funciones que pueden lanzar un error solo por su nombre: las funciones que lanzan errores llevan ! al final de su nombre. Esto es en comparación con las funciones que devuelven {:ok, value} o :error. Mira estos ejemplos de la biblioteca:

Map.fetch(%{a: 1}, :b)
# => :error
Map.fetch!(%{a: 1}, :b)
# => raises KeyError

Try/Rescue

Elixir proporciona una construcción para rescatar errores usando try .. rescue

try do
  raise RuntimeError, "error"
rescue
  e in RuntimeError -> :error
end

Veamos esta construcción:

  • Línea 1, el bloque se declara con try.
  • Línea 2, la llamada a la función que puede dar error se coloca aquí; en este caso estamos llamando a raise/2.
  • Línea 4, en la sección rescue, hacemos coincidencia de patrones con el nombre del módulo del error lanzado
    • del lado izquierdo de ->:
      • e coincide con el struct del error.
      • in es una palabra clave.
      • RuntimeError es el error del que queremos rescatar.
        • Si quisiéramos rescatar de todos los errores, podríamos usar _ en lugar del nombre del módulo u omitir por completo la palabra clave in.
    • del lado derecho:
      • las instrucciones que se ejecutarán si el error coincide.

Structs de error

Los errores (a veces también llamados «excepciones») que rescatas de esta forma son structs. En Elixir, rara vez se rescatan errores. Por lo general, el error rescatado se registra o se envía a un servicio externo de monitoreo, y luego se vuelve a lanzar. Esto significa que normalmente no nos importa la estructura interna del struct de error específico.

En el concepto Excepciones aprenderás más sobre los structs de error, incluido cómo definir tu propio error personalizado.

Instrucciones

Mientras trabajas en Instruments of Texas, se te encarga trabajar en una calculadora experimental de notación polaca inversa [RPN] escrita en Elixir. Tu equipo tiene un problema con algunas operaciones que lanzan errores y hacen que el proceso se caiga. Se te ha encargado escribir una función que envuelva a la función de operación para que los errores se puedan manejar de forma más elegante con código idiomático de Elixir.

1. Advertir al equipo

Implementa la función calculate!/2 para llamar a la función de operación con la pila como único argumento. La función de operación está definida en otro lugar, pero sabes que puede completarse con éxito o lanzar un error.

stack = []
operation = fn _ -> :ok end
RPNCalculator.calculate!(stack, operation)
# => :ok

stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate!(stack, operation)
# => ** (ArgumentError) An error occurred

Los nombres de funciones que terminan en ! son una advertencia para los programadores de que esta función puede lanzar un error

2. Envolver el error

Cuando investigas más, te das cuenta de que muchas funciones usan átomos y tuplas para indicar su éxito o fracaso. Implementa calculate/2 usando esta estrategia.

stack = []
operation = fn _ -> "operation completed" end
RPNCalculator.calculate(stack, operation)
# => {:ok, "operation completed"}

stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate(stack, operation)
# => :error

3. Transmitir el mensaje

Algunos de los errores contienen información importante que tus compañeros de trabajo necesitan para asegurar el correcto funcionamiento del sistema. Implementa calculate_verbose/2 para transmitir el mensaje de error. El error es una estructura que tiene un campo :message.

stack = []
operation = fn _ -> "operation completed" end
RPNCalculator.calculate_verbose(stack, operation)
# => {:ok, "operation completed"}

stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate_verbose(stack, operation)
# => {:error, "An error occurred"}
Editar en GitHub El enlace se abre en una ventana o una pestaña nuevas
Elixir Exercism

¿Todo listo para empezar Calculadora RPN?

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