desarrollo   2022-09-02 2022-09-02   4 minutos de lectura

¿Qué trae Elixir 1.14?

¿Qué trae Elixir 1.14?

  0   elixir     nueva versión     0   elixir   nueva versión

El jueves, 1 de septiembre, José Valim lanzó la versión 1.14 de Elixir con novedades y características para dar mayor juego al uso de Elixir, ¿quieres saber de qué se trata?

Las mejoras en esta versión se pueden enumerar como:

  1. Depuración
  2. PartitionSupervisor
  3. Mejoras en errores (de OTP 25)
  4. Mejoras en inspecciones reproducibles

Son las cuatro características de en esta versión que merecen mención. Hay otras mejoras y correcciones pero de menor importancia.

Depuración

Uno de los grandes atractivos de Elixir es su operador pipe (inspirado por F#) y la escritura de IO.inspect/2 dentro de estos bloques de código para obtener información en consola mientras desarrollamos. Sin embargo, código como el siguiente:

__ENV__.file
|> String.split("/", trim: true)
|> IO.inspect(label: "split")
|> List.last()
|> IO.inspect(label: "last")
|> File.exists?()
|> IO.inspect(label: "exists?")

Ejecutando en consola:

$ elixir inspect.exs
split: ["Users", "bombadil", "inspect.exs"]
last: "inspect.exs"
exists?: true

Nos dan una salida acorde al dato de cada parte, pero podemos hacerlo mucho mejor usando dbg/1:

__ENV__.file
|> String.split("/", trim: true)
|> List.last()
|> File.exists?()
|> dbg()

Ahora ejecutando:

$ elixir dbg.exs
[dbg.exs:5: (file)]
__ENV__.file #=> "/Users/bombadil/dbg.exs"
|> String.split("/", trim: true) #=> ["Users", "bombadil", "dbg.exs"]
|> List.last() #=> "dbg.exs"
|> File.exists?() #=> true

NOTA aquí no se ve, pero la salida es con colores para facilitar aún más su lectura.

Cada línea tiene su correspondiente salida. Podemos considerar esta acción similar al comando set +x de Shell Script donde vamos viendo los comandos en ejecución, pero esto va más allá porque no solo nos presenta los comandos, también el resultado de cada una de las partes de la tubería.

En IEx la depuración a través de IEx.pry/0 usando break!/1 nos permite obtener poco a poco la salida de dbg/1. Podemos ejecutar con iex nuestro último código y ver:

$ iex dbg.exs
Erlang/OTP 24 [erts-12.3.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]

Request to pry #PID<0.108.0> at dbg.exs:1

    1: __ENV__.file
    2: |> String.split("/", trim: true)
    3: |> List.last()
    4: |> File.exists?()

Allow? [Yn]

Una vez permitimos la ejecución, podemos ir línea a línea y viendo la salida:

Allow? [Yn] Y
Interactive Elixir (1.14.0) - press Ctrl+C to exit (type h() ENTER for help)
pry(1)> n
__ENV__.file #=> "/Users/bombadil/dbg.exs"

Break reached: dbg.exs:2

    1: __ENV__.file
    2: |> String.split("/", trim: true)
    3: |> List.last()
    4: |> File.exists?()
    5: |> dbg()

pry(1)>

Nos va indicando de la siguiente línea a ejecutar (dbg.exs:2) y según vemos tras pry(1)> n, la salida del depurador para la ejecución de esa línea.

PartitionSupervisor

Junto con Registry considero esta mejora esencial para la escalabilidad vertical de los sistemas. El supervisor de partición realiza por defecto una serie de particiones de los procesos que se inician en él. Podemos obtener el PID de cualquiera de los procesos proporcionando una clave y así dirigirnos siempre al mismo proceso siempre que se facilite la misma clave.

La ventaja está en ser el supervisor quien gestiona la cantidad de procesos y cómo acceder a ellos. Este comportamiento se explica en el libro Elixir/OTP: OTP para Alquimistas.

Mejoras en errores (de OTP 25)

Al igual que explicamos en el artículo sobre las nuevas características de Erlang/OTP 25, en Elixir también han mejorado los errores producidos por el uso de las cadenas de texto o binarios. Errores como estos:

iex(1)> int = 1
1
iex(2)> bin = "foo"
"foo"
iex(3)> int <> bin
** (ArgumentError) argument error while evaluating iex at line 3

Ahora en Elixir 1.14 obtenemos un error más elaborado para ayudarnos a entender el error:

iex(1)> int = 1
1
iex(2)> bin = "foo"
"foo"
iex(3)> int <> bin
** (ArgumentError) errors were found at the given arguments:

  * 1st argument: not a bitstring

    :erlang.bit_size(1)

Se aprecia ahora mayor detalle en el error indicando el tipo de dato originando el error y el porqué.

Mejoras en inspecciones reproducibles

Muchas veces cuando realizamos depuraciones nos encontramos con la necesidad de probar el conjunto de datos obtenido por pantalla en la consola pero podemos encontrarnos en la salida de la inspección con datos no evaluables como el siguiente:

iex(1)> MapSet.new() |> IO.inspect()
#MapSet<[]>

La almohadilla (#) es un comentario y por tanto no podemos emplear ese dato como código. Tampoco podemos obtener el valor de la estructura porque es privado e interno del módulo que gestiona ese dato. Necesitamos obtener la reproducción de la llamada de ese dato:

iex(1)> MapSet.new() |> IO.inspect()
MapSet.new([])

Puedes ver la llamada a la función para generar el dato con el parámetro explícito que indica el contenido del conjunto. En este caso ahora ya sí podríamos copiar el código y emplearlo directamente en la consola.

Conclusiones

Cada nueva versión de Elixir agrega nuevas formas de hacer más fácil la escritura de código para los programadores, el enfoque en estas versiones está en realizar una mejor especificación de los errores y facilitar la depuración del código. Así mismo hay muchos cambios pendientes para la siguiente versión donde se espera simplificar el concepto de lista de caracteres entre otras mejoras.

Elixir es un gran lenguaje y con cada versión mejora. Si aún no lo conoces, te invito a aprenderlo mejor a través del libro Elixir: Introducción para Alquimistas, echa un vistazo a los capítulos gratuitos y si quieres un descuento envíame un mensaje.

¿Qué te parecen estas mejoras? ¿Ya empleabas IO.inspect/1 e IO.inspect/2 con asiduidad? ¿Ves mejora al emplear IEx.pry/0? ¿Qué te parecen las mejoras con respecto a OTP 25? ¡Déjanos tu comentario!

Comentarios

No hay comentarios. Inicia sesión para enviar un comentario.