Elixir es lo que pasa cuando alguien mira Erlang, reconoce que su máquina virtual es extraordinaria y decide que el problema es todo lo demás: la sintaxis, las herramientas y la documentación. El resultado conserva el modelo de actores y la tolerancia a fallos, con la ergonomía de Ruby.
🎯 Por qué está en este programa
Elixir es un primo de la familia concurrente / actor (Atlas), junto a Erlang, con quien comparte máquina virtual.
Aporta al programa una lección de la clase 164 en estado puro: el ecosistema y la ergonomía pesan más que el modelo técnico. Erlang tenía el modelo desde 1986 y seguía siendo minoritario; Elixir no cambió el modelo —cambió la sintaxis y las herramientas— y multiplicó la adopción.
| Año | 2011; 1.0 en 2014; 1.18 actual, con análisis de tipos |
| Autoría | José Valim, que venía del núcleo de Ruby on Rails |
| Familia | Concurrente / actor; sobre la BEAM de Erlang |
| Paradigma | Funcional y concurrente, con datos inmutables |
| Tipado | Dinámico y fuerte; con inferencia de tipos gradual en desarrollo |
| Memoria | La de la BEAM: montón y recolector por proceso |
| Ejecución | Bytecode sobre la BEAM, con JIT |
| Estado | 🟢 En crecimiento: web en tiempo real, sistemas distribuidos, IoT |
José Valim era miembro del equipo central de Ruby on Rails y se topó con un problema estructural: Ruby no aprovecha bien los procesadores multinúcleo por su bloqueo global del intérprete (clase 135). Buscando alternativas, encontró la BEAM.
Su diagnóstico fue el que define esta ficha: la máquina virtual de Erlang es una obra maestra de ingeniería, y su lenguaje y sus herramientas son la barrera de entrada.
Así que en 2011 construyó Elixir: el mismo modelo, la misma máquina virtual, la misma interoperabilidad total con Erlang —se pueden llamar módulos de Erlang directamente, sin capa— y encima:
mix para construir, hex para dependencias con fichero de bloqueo
(clase 143), ExUnit para pruebas (clase 139) y documentación de primera clase.iex, una consola interactiva excelente.Phoenix (2014) hizo por Elixir lo que Rails hizo por Ruby, y en 2018 llegó LiveView: una forma de construir interfaces web interactivas sin escribir JavaScript, manteniendo el estado en el servidor con un proceso por usuario — algo que solo es viable porque los procesos de la BEAM son baratísimos (clase 168).
Uno, la canalización, que es la marca de la casa:
"1 2 3"
|> String.split()
|> Enum.map(&String.to_float/1)
|> Enum.sum()
|> pasa el resultado como primer argumento de la siguiente función. Viene de
F# y de OCaml, y hace que las transformaciones se lean en el orden en que
ocurren en lugar de anidadas.
Dos, el emparejamiento de patrones como control de flujo:
def procesar({:ok, valor}), do: "todo bien: #{valor}"
def procesar({:error, razon}), do: "falló: #{razon}"
Varias cláusulas de la misma función, seleccionadas por la forma del argumento — como en
Erlang y en Haskell. Y la convención {:ok, ...} / {:error, ...} es el
manejo de errores idiomático (clase 116): el resultado lleva el éxito o el fallo en su forma.
Y tres, las macros, con las que está construido el propio lenguaje:
defmodule MiPrueba do
use ExUnit.Case # ← una macro que inyecta el comportamiento de prueba
test "suma" do # ← 'test' también es una macro
assert 1 + 1 == 2 # ← y 'assert' MUESTRA los valores al fallar
end
end
if, unless, def y defmodule son macros, no palabras clave del lenguaje. Es la
homoiconicidad de Lisp (clase 123) aplicada con una sintaxis convencional — y es lo
que permite que Phoenix y Ecto tengan las API que tienen.
Y merece señalar lo que no cambió: el modelo de procesos, la supervisión y "déjalo fallar" son
exactamente los de Erlang. Un módulo de Erlang se llama desde Elixir con :modulo.funcion(), sin
puente ni conversión (clase 155).
mix format sin opciones, como gofmt (clase 146).elixir main.exs < entrada.txt # como guion
iex # consola interactiva
mix new proyecto && mix test # construcción y pruebas (clases 139 y 147)
mix format && mix credo # estilo y análisis (clase 146)
mix dialyzer # análisis de tipos con Dialyzer
Esta versión se escribe aquí y no está verificada en CI (clase 040).
[precio, cantidad, descuento] =
IO.gets("")
|> String.trim()
|> String.split()
|> Enum.map(&String.to_float/1)
total = precio * cantidad * (1 - descuento)
IO.puts("Total: #{:erlang.float_to_binary(total, decimals: 2)}")
Lo que hay que ver.
|>.[a, b, c] = ... es emparejamiento, igual que en Erlang: el = de Elixir es un
operador de coincidencia, no de asignación (clase 041).&String.to_float/1 es la captura de una función con su aridad — la aridad forma parte de la
identidad de la función, herencia directa de Erlang.:erlang.float_to_binary(...) llama a Erlang directamente, con : para los átomos de módulo.
Esa es la interoperabilidad total: no hay envoltorio ni conversión (clase 155).#{...} es interpolación de cadenas, tomada de Ruby — la ergonomía que Valim vino
a traer.⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: Erlang · Ruby · Clojure · Go · F#