jueves, 11 de diciembre de 2025

Elixir: Procesos ligeros y mensajes en acción

El hecho de que Elixir sea concurrente permite ejecutar múltiples tareas simultáneas, de tal manera que el sistema es más rápido y fácil de escalar. Esto se logra mediante procesos ligeros y aislados que se comunican entre sí por medio del paso de mensajes en lugar de compartir memoria: el Modelo de Actores.

A continuación mostraré un código ejemplo y después lo trataré de explicar:
defmodule Demo do
  def start do
    pid = spawn(fn -> loop() end)
    send(pid, {:saludo, "Hola desde el proceso principal"})
    send(pid, {:error, "Ahora llego un Error"})
  end

  defp loop do
    receive do
      {:saludo, msg} ->
        IO.puts("Proceso recibió: #{msg}")
        loop()  # vuelve a esperar más mensajes
      {:error, msg} ->
        IO.puts("Proceso recibió: #{msg}")
        loop()  # vuelve a esperar más mensajes
    end
  end
end

Demo.start()

Acá primero creamos un proceso con spawn con una función llamada loop() la cual se ejecuta de manera recursiva, para siempre quedar en espera de un nuevo mensaje que haga match con los patrones definidos. Dichos mensajes se pueden acceder desde el buzón de mensajes que tiene cada proceso en BEAM con la construcción de Elixir/Erlang llamada receive.

Seguido de la creación del proceso con spawn y de que se queda en espera, se envían dos mensajes al proceso recién creado. Accedemos a él pasando el PID del proceso al cual le queremos enviar dicho mensaje. Por ejemplo, si pasamos la tupla con: send(pid, {:saludo, "Hola desde el proceso principal"})

Se recibe en la función loop antes creada por el nuevo proceso, la cual hace match por el átomo :saludo y, por consiguiente, imprime:  IO.puts("Proceso recibió: #{msg}")   

Inmediatamente seguido de esto hay un evento recursivo para quedarse esperando un nuevo mensaje al proceso.

En mis anteriores aproximaciones al lenguaje me había costado más trabajo entender estas primeras lecciones, y ahora lo estoy realmente disfrutando. Además, el código y la sintaxis se ven super limpios y bonitos.

hiram

sábado, 22 de noviembre de 2025

Mi nuevo intento con Elixir: descubriendo el poder del Pattern Matching

Empezaré hablando de Elixir, el cual se ha convertido en los últimos años en un lenguaje que me he propuesto aprender en varias ocasiones, aunque mis intentos anteriores no han sido exitosos. Actualmente, en la empresa donde trabajo están desarrollando algunos proyectos en Elixir. Yo no estoy en ese equipo de desarrollo, pero me gustó mucho cuando le eché un vistazo a lo que están construyendo. Hay cosas de la programación funcional que me vuelan la cabeza, así que con esta pequeña entrada doy inicio a un nuevo intento, procurando que esta vez sí sea el bueno.

Me saltaré todo el tema de instalación; ya no entraré en esos detalles en mi blog porque existen muchos recursos que lo explican muy bien. En su lugar, trataré de subir más código para explicarme a mí mismo y tener un diario con los conceptos que vaya aprendiendo. Si esto ayuda a alguien más a comprender algo, será un punto extra. Al principio, allá por 2009, quería que este blog tuviera muchas visitas. Ahora solo quiero que funcione como mi diario y que, en algunos años, si mis hijas deciden programar o dedicarse a la tecnología, puedan leerlo y usarlo como referencia en lo que estén haciendo. Eso sería excelente. Y si no se dedican a la tecnología, también me gustaría que lo leyeran para recordar en qué estaba trabajando en estos años. Dicho lo anterior, la instalación está muy bien documentada en la página oficial del lenguaje, así que pasemos a hablar del primer punto: Pattern Matching.

La documentación oficial nos dice: “Pattern matching is a powerful part of Elixir. It allows us to match values, data structures, and even functions.”
Yo estoy viendo el pattern matching como una forma de evitar el uso de if/else. Este punto me sorprendió bastante: un lenguaje cuya sintaxis te “obliga” a no usar esas secuencias de control. Eso emociona, ¿no? Es algo nuevo. Seguramente mi perspectiva sobre qué es el pattern matching todavía es muy limitada, pero apenas voy empezando. Algo que también comprendí de esa definición es que puede matchear estructuras de datos e incluso funciones, lo cual no hace más que aumentar mi interés por este lenguaje.

# Reto 1 – Saludos con pattern matching
defmodule Greeter do
    def greet("bitxbit"), do: "¡Hola, BitBit!"
    def greet(nil), do: "¡Hola, desconocido!"
    def greet(_), do: "¡Hola, mundo!"
end

# Aquí abajo puedes poner pruebas rápidas si quieres
IO.puts(Greeter.greet("bitxbit"))
IO.puts(Greeter.greet("Test"))
IO.puts(Greeter.greet(nil))

Aquí vemos un par de cosas: primero, no necesitamos sentencias de control para matchear las funciones del módulo Greeter. Esto me gusta mucho: el código se ve limpio. Solo a manera de comparativa, y sin buscar optimizar nada, haré lo mismo en C# usando un método con if/else.

using System;

class Greeter
{
    public string Greet(string name)
    {
        if (name == "bitxbit")
        {
            return "¡Hola, BitBit!";
        }
        else if (name == null)
        {
            return "¡Hola, desconocido!";
        }
        else
        {
            return "¡Hola, mundo!";
        }
    }
}

class Program
{
    static void Main()
    {
        var greeter = new Greeter();

        Console.WriteLine(greeter.Greet("bitxbit")); // ¡Hola, BitBit!
        Console.WriteLine(greeter.Greet("Test"));    // ¡Hola, mundo!
        Console.WriteLine(greeter.Greet(null));      // ¡Hola, desconocido!
    }
}

En Elixir, defines varias cláusulas de la misma función y el runtime (BEAM) decide cuál usar según el patrón, la forma en que lo define es de arriba hacia abajo, en mi ejemplo con elixir se puede ver como coloque primero el nulo antes de que matche con cualquier cosa, porque si el _ estvuera primero este matchearia y el nil nunca se ejecutaria.

En C#, defines una sola función y dentro usas if/else para decidir qué devolver.

Ahora lo haremos un poco más interesante colocare otro ejemplo donde utilizo estructura de datos como lista, tuplas y diccionarios.

defmodule Classifier do
    def classify(nil), do: "Es nulo"
    def classify(x) when is_number(x) and x > 0, do: "Es positivo"
    def classify(x) when is_number(x) and x < 0, do: "Es negativo"
    def classify(0), do: "Es cero"
    def classify([]), do: "Es una lista vacia"
    def classify(list) when length(list) > 1, do: "Es una lista con #{length(list)} elementos"
    def classify(tuple) when tuple_size(tuple) > 1, do: "Es una tupla con #{tuple_size(tuple)} elementos"
    def classify(%{name: name}), do: "Hola, #{name}"
    def classify(_), do: "Cualquier otra cosa"
end

IO.puts(Classifier.classify(nil))
IO.puts(Classifier.classify(10))
IO.puts(Classifier.classify(-5))
IO.puts(Classifier.classify(0))
IO.puts(Classifier.classify("hola"))
IO.puts(Classifier.classify([]))
IO.puts(Classifier.classify([1,2,3]))
IO.puts(Classifier.classify({:ok, 42}))
IO.puts(Classifier.classify(%{name: "Hiram"}))
IO.puts(Classifier.classify("$"))

Con esto termino esta entrada sobre pattern matching. De este último código, lo que me llama la atención es cómo hace el match con el paso de parámetros de una lista y cómo matchea con una cláusula de función en particular. Mientras escribo esto, sigo leyendo e investigando dudas que tengo sobre el mismo lenguaje. Es el día 3 desde que empecé a leer sobre Elixir y, como ya he dicho antes, no deja de interesarme cada vez más.

hiram

jueves, 20 de noviembre de 2025

Vamos a hacer un sudo apt-get update

Siempre dicen que uno vuelve a donde fue feliz, y antes de escribir una nueva entrada me di una pasada por algunos de mis antiguos posts. Vaya que me emocioné al ver y leer todos los temas en los que andaba en aquel entonces. Tengo alrededor de 7 años usando Windows nuevamente como SO principal, por trabajo. En un principio pensé en que tendría el tiempo de tener una segunda computadora en mi casa con Debian, a la cual llegaría por las noches a programar o a hacer algo, pero la verdad es que con tantas cosas que tenemos ya en la vida adulta es casi imposible. Lo cierto es que el trabajo me ha llevado por caminos que nunca pensé cruzar, así que tiempo es lo que menos he tenido estos últimos 7 años.

Me estoy proponiendo revivir esta pequeña libreta de notas para ir colocando acá algunas cosas técnicas y algunas otras personales. Como por ejemplo, que ya tengo dos hermosas princesas en mi vida: una llamada Sofía y la más pequeña llamada Renata. Seguro más adelante saldrán en alguna entrada hablando sobre ellas, porque ya las ando induciendo a la tecnología/programación. Estoy intentándolo hacer poco a poco para que no se sientan abrumadas y mucho menos obligadas. Hace un mes aproximadamente, Sofía me pidió que hiciéramos un carrito robot, así que mal no voy con mis planes. Veremos al final del camino qué deciden ellas.

hiram