Introducción
Elixir es un lenguaje de programación puramente funcional que funciona sobre la VM de Erlang. Esto quiere decir que nuestro código será transpilado a Erlang y ejecutado por dicha máquina virtual.
Para hacer un símil, es lo mismo que ocurre con Kotlin y Java. Nuestro código es transpilado de Kotlin a Java, se compila a ficheros .class y estos son ejecutados por la máquina virtual.
Curiosidades
Tenemos que entender que, al tratarse de un lenguaje puramente funcional, no vamos a encontrar clases. Por el contrario, veremos módulos que contienen funciones, las cuales esperan recibir parámetros y pueden concatenarse con otras con la idea de recibir el valor devuelto por la primera y seguir trabajando con él.
Matching operator y pattern matching
Es uno de los puntos más importantes del lenguaje, puesto que nos permitirá no solo asignar valores:
x = 1
Sino también aplicar desestructuración a nuestras variables:
{a, b, c} = {:hello, "world", 42}
Para el ejemplo anterior podemos afirmar las siguientes correspondencias: a -> :hello, b -> "world", c -> 42.
Este mismo patrón también nos vale para los arrays:
{a, b, c} = [:hello, "world", 42]
Otro caso muy típico es hacer desestructuraciones más complejas:
[head | tail] = [1, 2, 3]
En este caso head -> 1, mientras que tail -> [2, 3].
Utilizando esta misma sintaxis también podemos añadir contenido a la lista:
list = [1, 2, 3]
new_list = [0 | list]
De esta forma el resultado sería [0, 1, 2, 3].
Otro caso interesante es el uso del operador _. Es un operador reservado para desestructuración que nunca puede ser leído:
[head | _] = [1, 2, 3]
En esta ocasión head -> 1, mientras que _ no puede ser leído. Es muy útil cuando el resto de datos son irrelevantes para nuestro código.
Pipe operator |>
Este operador viene a ser un método de concatenación. Por ejemplo, si quisiéramos definir una sucesión de llamadas de una forma clásica:
defmodule Socracan do
def reversed_digits(number) do
Integer.digits(Enum.reverse(number))
end
end
En este caso recibimos un número, lo invertimos y lo dividimos en dígitos. Aunque el código conste de una sola línea, resulta difícil de comprender. Usando el operador |> podemos hacerlo más legible:
defmodule Socracan do
def reversed_digits(number) do
number
|> Integer.digits()
|> Enum.reverse()
end
end
Aquí number es pasado al método Integer.digits y, a su vez, este le pasa su resultado a Enum.reverse.
Otra cosa que me resultó curiosa en Elixir es que, aparte de los tests unitarios a los que estamos acostumbrados:
defmodule ExampleTest do
use ExUnit.Case
doctest Example
test "greets the world" do
assert Example.hello() == :world
end
end
También tenemos los tests de documentación, los doctest. Estos tests hacen una prueba sencilla: dada una entrada, comprueban la salida y se colocan encima de la definición del método como documentación. Es una manera de tener documentación viva que, además, se autocomprueba.
defmodule Example do
@moduledoc """
Documentation for Example.
"""
@doc """
Hello world.
## Examples
iex> Example.hello()
:world
"""
def hello do
:world
end
end
Si quieres empezar con Elixir y no sabes por dónde, existe un repositorio muy interesante con koans para practicar con el lenguaje. Te va llevando desde lo más básico a casos más complejos con tests en rojo que tienes que completar sustituyendo los tres guiones bajos ___.