💧 Elixir — 2011

⬅️ Atlas · 🗂️ Todas las fichas · 📚 Índice de clases

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

📜 Historia

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:

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).

🏭 Dónde vive hoy

🧠 Lo que enseña: la misma potencia con otra puerta

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).

🔄 Lo que se ha modernizado

⚙️ Cómo se ejecuta hoy

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

🧪 El programa de la clase 041 en Elixir

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.

📚 Fuentes y bibliografía


⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: Erlang · Ruby · Clojure · Go · F#