Configuración inicial

Prepara tu entorno de desarrollo para Elixir y familiarízate con las herramientas básicas. ⏱️ 1 hora

Instalación de Elixir y Erlang

Elixir corre sobre la máquina virtual BEAM de Erlang, así que necesitas ambos. La forma más limpia de instalarlos es usando asdf, un gestor de versiones que te permite tener múltiples versiones instaladas.

Opción A: Con asdf (recomendado)

# Instalar asdf (si no lo tienes)
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.13.1
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc
source ~/.bashrc

# Añadir plugins de Erlang y Elixir
asdf plugin add erlang
asdf plugin add elixir

# Instalar versiones (esto tarda un poco)
asdf install erlang 26.2.1
asdf install elixir 1.16.0-otp-26

# Establecer como versiones globales
asdf global erlang 26.2.1
asdf global elixir 1.16.0-otp-26

Opción B: Con el gestor de paquetes del sistema

En Ubuntu/Debian:

sudo apt update
sudo apt install erlang elixir

En macOS con Homebrew:

brew install erlang elixir

Verificar la instalación

# Debe mostrar Elixir 1.15+ 
elixir --version

# Debe mostrar Erlang/OTP 26+
erl -version
⚠️ Versiones mínimas

Para este libro necesitas Elixir 1.15+ y Erlang/OTP 26+. Versiones anteriores no tienen algunas características que usaremos, especialmente en la parte de distribución.

El shell interactivo IEx

IEx (Interactive Elixir) es tu herramienta principal de exploración. Ejecútalo con:

iex

Verás un prompt donde puedes evaluar expresiones Elixir directamente:

iex(1)> 1 + 1
2

iex(2)> "hola" <> " mundo"
"hola mundo"

iex(3)> [1, 2, 3] |> Enum.map(fn x -> x * 2 end)
[2, 4, 6]

Comandos útiles de IEx

Comando Descripción
h/1 Ayuda sobre una función. Ej: h Enum.map
i/1 Información sobre un valor. Ej: i "hola"
c/1 Compila un archivo. Ej: c "mi_modulo.ex"
r/1 Recompila un módulo. Ej: r MiModulo
v/0 Último valor evaluado
Ctrl+C, Ctrl+C Salir de IEx
💡 Tab completion

IEx tiene autocompletado. Escribe Enum. y pulsa Tab para ver todas las funciones del módulo Enum.

Mix: el gestor de proyectos

Mix es el equivalente a Cargo (Rust) o Composer (PHP). Crea proyectos, gestiona dependencias, ejecuta tests, y más.

Crear un proyecto nuevo

# Crear proyecto básico
mix new mi_proyecto
cd mi_proyecto

# Estructura generada:
mi_proyecto/
├── lib/
│   └── mi_proyecto.ex      # Código principal
├── test/
│   ├── mi_proyecto_test.exs
│   └── test_helper.exs
├── mix.exs                  # Configuración del proyecto
└── README.md

Comandos Mix esenciales

# Compilar el proyecto
mix compile

# Ejecutar tests
mix test

# Abrir IEx con el proyecto cargado
iex -S mix

# Obtener dependencias
mix deps.get

# Formatear código
mix format

Configuración del editor

Para VS Code, instala la extensión ElixirLS. Te da:

Configuración recomendada en settings.json:

{
  "[elixir]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "JakeBecker.elixir-ls"
  },
  "elixirLS.suggestSpecs": true,
  "elixirLS.dialyzerEnabled": true
}
🔴 Nota sobre Erlang

A lo largo del libro, estos recuadros rojos indicarán cuándo necesitas interactuar directamente con Erlang o sus librerías. El 90% del tiempo usarás Elixir puro, pero ciertas funcionalidades de bajo nivel (especialmente networking y distribución) requieren llamar a módulos Erlang directamente.

Primer programa: verificación del entorno

Crea un proyecto para verificar que todo funciona:

mix new verificar_entorno
cd verificar_entorno

Reemplaza el contenido de lib/verificar_entorno.ex:

defmodule VerificarEntorno do
  def info do
    IO.puts("""
    ═══════════════════════════════════════
    Entorno Elixir/Erlang configurado
    ═══════════════════════════════════════
    Elixir: #{System.version()}
    Erlang: #{:erlang.system_info(:otp_release)}
    BEAM:   #{:erlang.system_info(:version)}
    
    Schedulers: #{System.schedulers_online()} online
    Arquitectura: #{:erlang.system_info(:system_architecture)}
    ═══════════════════════════════════════
    """)
  end

  def test_concurrencia do
    # Crear 10,000 procesos para verificar que la BEAM funciona
    inicio = System.monotonic_time(:microsecond)
    
    1..10_000
    |> Enum.map(fn _ -> spawn(fn -> :ok end) end)
    |> Enum.each(fn pid -> Process.monitor(pid) end)
    
    fin = System.monotonic_time(:microsecond)
    
    IO.puts("10,000 procesos creados en #{fin - inicio} μs")
  end
end

Ejecuta para verificar:

$ iex -S mix
iex(1)> VerificarEntorno.info()
═══════════════════════════════════════
Entorno Elixir/Erlang configurado
═══════════════════════════════════════
Elixir: 1.16.0
Erlang: 26
BEAM:   14.2.1

Schedulers: 8 online
Arquitectura: x86_64-pc-linux-gnu
═══════════════════════════════════════

iex(2)> VerificarEntorno.test_concurrencia()
10,000 procesos creados en 4523 μs
📊 Sobre los schedulers

Los schedulers son los hilos del sistema operativo que la BEAM usa para ejecutar procesos Elixir. Por defecto hay uno por cada núcleo de CPU. Esto es crucial para entender el rendimiento de sistemas distribuidos.

Ejercicio 0.1 Explorar IEx Básico
  1. Abre iex y usa h Enum.map para ver la documentación
  2. Usa i [1, 2, 3] para inspeccionar una lista
  3. Evalúa :erlang.system_info(:process_count) para ver cuántos procesos hay activos
  4. Crea 100 procesos con for _ <- 1..100, do: spawn(fn -> :timer.sleep(5000) end) y vuelve a verificar el conteo
Ejercicio 0.2 Modificar el proyecto Básico

Añade una función test_memoria/0 al módulo VerificarEntorno que muestre:

  • Memoria total del sistema: :erlang.memory(:total)
  • Memoria usada por procesos: :erlang.memory(:processes)
  • Memoria usada por binarios: :erlang.memory(:binary)

Pista: divide los valores por 1024*1024 para obtener megabytes.

Estructura del resto del libro

A partir de aquí, cada capítulo seguirá este formato:

Todo el código está probado en Elixir 1.16 + OTP 26. Si algo no funciona, verifica tus versiones primero.