1 puntos por GN⁺ 2025-10-17 | 1 comentarios | Compartir por WhatsApp
  • La versión Elixir 1.19 permite detectar más errores con mayor rapidez gracias al fortalecimiento del sistema de tipos y a mejoras en el rendimiento de compilación
  • La inferencia de tipos se amplía a funciones anónimas y protocolos, lo que habilita una validación automática más amplia incluso sin anotaciones de tipo del usuario
  • En proyectos grandes ofrece hasta 4 veces más velocidad de compilación, e incluye optimizaciones de compilación en paralelo y carga de código
  • También se refuerzan el ecosistema y la transparencia de la cadena de suministro con soporte para Erlang/OTP 28 y la adopción de certificación OpenChain
  • Además, incluye varias funciones como mejoras en el análisis de opciones, mayor capacidad de depuración en ExUnit y mejor accesibilidad a la documentación basada en shell

Principales mejoras de Elixir 1.19

Mejoras en el sistema de tipos

Inferencia de tipos en todos los componentes

  • Type inference (inferencia de tipos) es una función que determina automáticamente el tipo de una expresión en tiempo de compilación
  • Antes se buscaba dar soporte a la inferencia de tipos principalmente en patrones, guardas y valores de retorno, pero en esta versión se introduce la inferencia de tipos para todos los componentes (excepto las guardas)
  • Como la inferencia toma en cuenta también las llamadas a funciones dentro del módulo y a funciones de la biblioteca estándar de Elixir, funciones que antes se inferían como dynamic() -> boolean() ahora pueden inferirse de forma más precisa, por ejemplo como integer() -> boolean()
  • La inferencia de tipos implica varios trade-offs como velocidad de compilación, expresividad, compilación incremental y claridad de errores, por lo que más adelante también se incorporarán inferencia de tipos en guardas e información de tipos de dependencias
  • Si una función tiene una firma de tipos explícita, entonces en lugar de inferencia de tipos se aplica una verificación de tipos explícita, que solo permite tipos acordes con las anotaciones del usuario

Verificación de tipos en despacho e implementación de protocolos

  • Elixir ahora aplica verificación de tipos al invocar e implementar protocolos
  • Por ejemplo, si se pasa a una interpolación de cadenas un tipo que no implementa el protocolo String.Chars, se mostrará un mensaje de advertencia
  • También se generará una advertencia si en una comprensión for se pasa como generador un tipo que no cumple con el protocolo Enumerable
  • Estas verificaciones de tipos permiten prevenir más bugs en tiempo de compilación

Inferencia y verificación de tipos en funciones anónimas

  • Elixir 1.19 añade soporte para inferencia y verificación de tipos en funciones anónimas
  • Por ejemplo, si a una función anónima que espera un tipo %{} se le pasa un tipo incorrecto como "hello", esto puede detectarse de inmediato como una advertencia en tiempo de compilación
  • La inferencia de tipos también se aplica a capturas de funciones (como &String.to_integer/1), con lo que se amplía el alcance de la validación automática de tipos

Referencias y socios

  • Este sistema de tipos fue desarrollado mediante una alianza entre CNRS y Remote
  • Fresha, *Starfish* *, Dashbit y otros brindaron apoyo

Mayor velocidad de compilación en proyectos grandes

Mejora de cuellos de botella en la carga de código

  • Antes, los módulos se cargaban inmediatamente al definirse, pero en esta versión se cambió a una estrategia de lazy loading (carga diferida)
  • Gracias a esto, se reduce la carga sobre el servidor de código y mejora el rendimiento de la compilación en paralelo, lo que eleva la velocidad de compilación en proyectos grandes a más del doble
  • Dos puntos importantes a tener en cuenta
    • Si durante la compilación se crea un proceso separado y este intenta acceder a módulos dentro del mismo proyecto, puede ocurrir que falte la carga; para evitarlo se usan Kernel.ParallelCompiler.pmap/2 o Code.ensure_compiled!/1, entre otros
    • Dentro del callback @on_load, al invocar módulos del mismo proyecto pueden producirse errores; si es necesario, se puede usar la opción @compile {:autoload, true}
  • En ambos casos antes podían producirse errores de compilación no deterministas, pero con esta mejora ahora se garantiza un entorno de compilación determinista (reproducible)

Compilación paralela de dependencias

  • Se da soporte a la compilación paralela de dependencias (dependencies) mediante la variable de entorno MIX_OS_DEPS_COMPILE_PARTITION_COUNT
  • Como las dependencias se compilan en paralelo aprovechando varios procesos del sistema operativo al mismo tiempo, el rendimiento de compilación puede mejorar hasta 4 veces, según el tamaño del proyecto y la cantidad de núcleos de CPU
  • De forma experimental, configurar un valor equivalente a aproximadamente la mitad del total de núcleos resulta efectivo para el uso de recursos
  • Como la paralelización puede aumentar el uso de memoria, se requiere precaución al aplicarla en CI o en servidores de build

Soporte para Erlang/OTP 28

  • Elixir 1.19 soporta oficialmente Erlang/OTP 28.1+
  • Debido a cambios en la representación de expresiones regulares en Erlang/OTP 28, ya no es posible usar expresiones regulares como valor por defecto de un struct
  • Al inicializar un struct, sí sigue siendo posible usar expresiones regulares

Adopción de certificación OpenChain

  • Esta versión es la primera en comenzar a cumplir con la especificación OpenChain
  • Cada release incluye un SBoM (Source Bill of Materials) en formatos CycloneDX 1.6/SPDX 2.3
  • Esto mejora la transparencia de la cadena de suministro de los componentes y licencias del release, y contribuye a una gestión más estricta
  • Este trabajo fue realizado por Jonatan Männchen y patrocinado por la Erlang Ecosystem Foundation

Otras mejoras

  • Se añadieron diversas mejoras en herramientas y bibliotecas, como análisis de opciones, depuración y rendimiento de ExUnit, y accesibilidad a documentación basada en shell
  • Para notas de versión más detalladas, consulta el CHANGELOG

1 comentarios

 
GN⁺ 2025-10-17
Comentarios de Hacker News
  • Se destaca que la forma en que Elixir está introduciendo gradualmente el chequeo automático de tipos es un excelente ejemplo de mejora de lenguaje del que otros lenguajes de programación podrían aprender; ha habido muchos casos en los que grandes cambios dividieron al ecosistema en dos, y da tranquilidad que José haya dejado claro desde 2018 que el lenguaje en sí ya está completo. Explica que el lenguaje y el core ya no se van a romper, lo que da mucha estabilidad, y recomienda la charla relacionada. Le impresiona una gestión tan consistente y bien llevada.

    • Solo se le vienen a la mente Python 3 y Perl 6 como casos de división del ecosistema por grandes cambios en lenguajes importantes; como esos dos cambios fueron tan impactantes, da la impresión de que cualquier otro cambio en un lenguaje también es enorme.
    • En Elixir nunca siente que lo persigan para actualizar versiones; más bien va viendo los cambios que se introducen y termina queriendo actualizar por alguna función nueva útil. No siente ansiedad ni estrés como cuando te obligan a cambiar de versión a la fuerza.
    • Lleva usando Elixir en producción desde 2017, y cada actualización ha sido mucho más fluida de lo que esperaba. De hecho, las actualizaciones de Erlang/OTP muchas veces han sido más complejas por temas de compatibilidad, así que normalmente usa la versión más reciente de Elixir pero espera uno o dos meses más antes de actualizar OTP, hasta que se resuelvan posibles conflictos.
    • Elixir todavía se siente algo incompleto y poco conveniente, y necesita una guía más clara para alcanzar sus objetivos y una estabilización del ecosistema. Siente que muchos paquetes están abandonados o tienen documentación insuficiente, lo que dificulta seguir el ritmo de cambios del ecosistema Phoenix. También hay muchos usuarios que no quieren LiveViews ni ciertos sistemas de componentes, y la barrera de entrada para la compatibilidad con otras herramientas y tecnologías es alta. En Python 3, el salto de 2 a 3 era necesario y se logró relativamente bien con herramientas automáticas de migración, aunque hubo mucho ensayo y error. En cambio, Ruby 3 introdujo archivos de tipos externos y una fragmentación de herramientas que terminó causando más confusión; además, entre boilerplate, problemas de gobernanza y casos como el secuestro de gems, terminó usando menos Ruby. Enfatiza que incluso un gran lenguaje puede arruinarse por una gestión inmadura, así que la colaboración madura, la comunicación y una buena gestión del cambio son fundamentales. Cree que los cambios de diseño de lenguaje deben pasar por suficiente experimentación previa, mucha prudencia y una comunicación anticipada suficiente hacia los usuarios para minimizar confusiones innecesarias. Espera que Elixir/Phoenix/OTP se vuelvan aún más fáciles, potentes, productivos y con mejor rendimiento, para que distintos tipos de usuarios puedan usarlos con confianza, y recomienda recursos como Livebook y el track de Elixir en Exercism.
  • Elixir sigue lanzando grandes funciones y mejoras de forma constante, y avanza con estabilidad. La estructura del lenguaje es excelente y sus creadores siguen marcando una dirección correcta de forma continua, lo cual resulta realmente impresionante. Más bien da pena no tener oportunidades cotidianas para usar Elixir.

    • Quería tanto usar Elixir que incluso renunció a su trabajo y fundó su propia empresa.
  • Comparte datos experimentales sobre la velocidad de compilación de dependencias en Phoenix. En una app pequeña con solo las dependencias básicas de Phoenix, en una Mac M1 Max, se midieron los siguientes tiempos de compilación según el valor de la variable de entorno MIX_OS_DEPS_COMPILE_PARTITION_COUNT:

    PARTITION_COUNT=1:  12.336초 (유저 32.30s, 시스템 7.23s, CPU 320%)
    PARTITION_COUNT=5:  6.970초 (유저 0.37s, 시스템 0.49s, CPU 12%)
    PARTITION_COUNT=10: 7.236초 (유저 0.38s, 시스템 0.50s, CPU 12%)
    

    Entre cada prueba borró la caché con el comando rm -rf _build.

    • Parece que las ejecuciones posteriores se midieron ya con la caché aplicada, y quizá la compilación nativa se hizo directamente dentro de la carpeta dep, por lo que no quedaron rastros en _build.
    • No entiende por qué los resultados de benchmark sobre esta función del release recibieron votos negativos, y pregunta si alguien podría explicar su opinión.
  • En los últimos meses llegó a gustarle mucho Gleam. También le alegra la introducción del sistema de tipos en Elixir, pero antes este punto era uno de los principales factores que le dificultaban adoptar Elixir. Le gustaría volver a intentarlo algún día, aunque le preocupa que termine siendo como TypeScript en JavaScript: tipado solo en apariencia, mientras que en muchas libs o paquetes todo acaba siendo dynamic/any. Se pregunta si esa preocupación será infundada. BEAM es realmente excelente.

    • El contexto es distinto al de TypeScript. Gracias al pattern matching, parece que al menos un 50% de una base de código existente en Elixir podría inferirse por tipos, y como Elixir puro ofrece tipos de base, el código que se mantenga probablemente se irá tipando rápidamente. No le gustan mucho los sistemas de tipos y solo usa JS, pero en Elixir la aplicación de tipos se siente natural. TypeScript va hacia arriba, mientras que en Elixir el proceso se propaga naturalmente hacia abajo.
    • Gleam no puede aprovechar perfectamente las verdaderas fortalezas de OTP/BEAM; ese atractivo solo lo ofrece Elixir.
    • Elixir ya tenía desde antes conceptos de tipos como tipos primitivos, structs y destructuración basada en shape, y se puede hacer chequeo de tipos con herramientas como Dialyzer y TypedStruct. No es un lenguaje absurdamente sin tipos como JavaScript.
    • Gleam también está bien, pero en la JVM Kotlin es un lenguaje tipado con sintaxis similar a Ruby y además se puede usar compile-to-JS.
  • Siente que Elixir es el entorno de desarrollo web más prometedor. Cada vez que se encuentra con organizaciones o equipos que usan Elixir en el trabajo real, le parece que su nivel suele ser más alto que el promedio. Cree que, en contextos donde se necesita desarrollo continuo, Elixir sigue marcando dirección y estándares.

  • Presenta que este release de Elixir empezó a dar soporte a formatos Source SBoM como CycloneDX 1.6 o superior y SPDX 2.3 o superior. Es algo realmente de agradecer que la gestión de SBOM se haga a nivel del lenguaje. Lamentablemente, en su empresa actual no usan Elixir.

  • Si alguien quiere contribuir a un proyecto open source de Elixir usado de verdad, comenta que componentes principales del antiguo Mozilla Hubs siguen desarrollándose en Elixir como proyectos independientes. Recomienda ver Hubs Foundation/reticulum.

  • Basándose en la biblioteca estándar de Elixir, es posible hacer inferencia de tipos en tiempo de compilación para situaciones específicas de la app, como booleanos dentro de tipos dinámicos o booleanos a partir de enteros.

  • No tiene experiencia desarrollando con Elixir, pero es fan. Antes le gustaban la practicidad y la belleza de Ruby, pero cambió de lenguaje al sentirse atraído por los sistemas de tipos. Tanto Elixir como Ruby introdujeron sistemas de tipos, pero ahora usa principalmente Kotlin, que sintácticamente se siente como un “Ruby tipado”.

    • Kotlin se parece casi exactamente a lo que de verdad queríamos de jruby.
  • Está usando Soketi con el sdk de pusher para manejar broadcast de eventos. La app tiene una estructura mixta con endpoints en tiempo real y endpoints REST, y la carga de cómputo en tiempo real no es tan alta, aunque si hace falta piensa manejarla por separado con Go. También planea agregar funciones de colaboración pronto, y se pregunta si en una situación así tiene sentido adoptar Phoenix.