Esta publicación apareció originalmente en el sitio web de David y se republica aquí con permiso
En enero del año pasado, Exercism anunció un nuevo programa llamado 12in23, en el que retaba a los participantes a probar 12 lenguajes de programación nuevos en 2023. Cada mes tendría un tema (como «Analytical April» o «Object Oriented October») y destacaría lenguajes concretos para probar. Me encanta aprender cosas nuevas y me he vuelto un poco nerd de los lenguajes (de programación), así que decidí intentarlo. ¡12 lenguajes, 12 meses!
Ahora que el año casi termina, estoy increíblemente contento con cómo salió el proyecto. Logré probar 12 lenguajes nuevos, conocí a gente genial en la comunidad de Exercism y, de paso, publiqué algunas contribuciones interesantes de código abierto. En esta publicación los repaso todos y hablo de lo que me aportó cada uno.
Cómo elegí los lenguajes
Definí algunas pautas para el año que me ayudaran a aprovechar al máximo la experiencia:
- Los lenguajes debían ser totalmente nuevos para mí, o al menos lo bastante desconocidos como para sentir que estaba aprendiendo mucho.
- Los lenguajes elegidos debían ser (potencialmente) útiles para seguir aprendiendo de ellos en el futuro. El proyecto era solo por diversión, pero quiero dedicar mi tiempo a aprender cosas (al menos en parte) útiles.
- Instalaría todas las herramientas locales y el plugin de VSCode para cualquier lenguaje que usara. Quería comparar los lenguajes en igualdad de condiciones, con la mayor cantidad posible de sugerencias de tipos e intellisense. En la universidad hacía todas mis tareas de programación en Sublime Text, sin ningún linter ni autocompletado. Me preocupaba que, si aprendía a programar usando todas esas herramientas, dependería demasiado de ellas y no llegaría a ser un buen programador. En cambio, pasó lo contrario. Cuanta más cognición puedo delegar en mis herramientas, más puedo pensar en el problema real que tengo delante. No te aprendas las cosas de memoria; aprende a encontrarlas.
¡Empecemos!

Enero (sin tema)
Cuando empezó enero, el equipo de Exercism todavía estaba eligiendo los temas mensuales, así que el lenguaje de ese mes quedó a mi elección. Sin una dirección clara, arranqué el año con Go. A mediados de 2022 había hecho un curso intensivo del lenguaje, pero no lo había usado mucho desde entonces y no me sentía nada competente.
Go es un lenguaje interesante. Su compilador estricto hace que Tu Programa Vaya a Ser Correcto y no te deja avanzar ni un centímetro hasta que considera que es seguro hacerlo.1 Su forma tan verbosa de manejar los errores hace que nunca te lleves sorpresas (a costa de escribir if err != nil { return err } muchísimas, muchísimas veces). Hace un buen trabajo convirtiendo lo difícil en fácil (como el paralelismo mediante canales), pero también complica algunas cosas fáciles (la manipulación de strings). Tiene una biblioteca estándar robusta, lo que significa que puedes resolver la mayoría de las tareas sin módulos de terceros. Me gusta que gran parte del ecosistema (formatear, instalar, compilar, etc.) sea propio del lenguaje y venga integrado en el comando go. El lenguaje tiene sus detractores, pero creo que cumple bastante bien sus objetivos de corrección y mantenibilidad.
No lo disfruté tanto como para elegirlo como primera opción, pero es una gran herramienta para tener a mano en programas sensibles al rendimiento, como mostrar la ruta anidada en el prompt de mi shell.
Functional February

Febrero se metió de lleno en los lenguajes funcionales, que son una rama de corte matemático de los lenguajes imperativos más comunes. Los lenguajes funcionales son conocidos por sus funciones «puras» (sin efectos secundarios). Elegí Elixir, sobre todo porque mi amigo Caleb lo ha usado para Advent of Code y habla maravillas de él.
Disfruté bastante mi tiempo con Elixir. Se inspiró en Ruby (lo cual tiene sentido; su creador, José Valim, fue colaborador central de Rails). Me resultó sencillo expresar conceptos funcionales como el encadenamiento de métodos. Me encantó todo el azúcar sintáctico que lo hacía fácil, como el operador de tubería (|>):
foo(bar(baz(new_function(other_function()))))
# becomes
other_function() |> new_function() |> baz() |> bar() |> foo()
También fue la primera vez que trabajé con macros, es decir, código que escribe código. Como los programas de Elixir pueden expresarse en un AST que a su vez es código Elixir válido, es fácil escribir código que produzca otro código válido. Es un concepto genial que Elixir hace fácil. También me gustó que las funciones pudieran hacer coincidencia de patrones según la forma de sus argumentos, de modo que las llamadas se dirigieran a la implementación adecuada:
defmodule TuplePrinter do
def print({a}) do
IO.puts("single")
IO.puts(a)
end
def print({a, b}) do
IO.puts("double")
IO.puts(a)
IO.puts(b)
end
end
TuplePrinter.print({1})
TuplePrinter.print({2, 2})
# single
# 1
# double
# 2
# 2
Parece el tipo de característica que o es genial o convierte tu código en un espagueti total. En cualquier caso, ¡era un concepto genial!
Elixir también se beneficia de ejecutarse dentro de la máquina virtual BEAM de Erlang, lo que le da un gran ecosistema con el que comunicarse. Es excelente para la concurrencia y es el núcleo del querido framework web Phoenix.
Aunque no tengo una necesidad inmediata de usar Elixir, me resultó muy divertido trabajar con él y sin duda estaría abierto a retomarlo. Además, fue un reto interesante abordar problemas conocidos de formas poco habituales (en concreto, de forma recursiva).
Mechanical March
Marzo se centró en los lenguajes «de sistemas», que se compilan a código máquina.
De las opciones disponibles, Go era el único lenguaje que me interesaba.2 Ahora bien, los lectores astutos notarán que ya había hecho un mes de Go, así que repetirlo no contaría para mis 12. Bueno, cuando lo elegí para enero, todavía no habían anunciado que habría temas, así que no me di cuenta de que me estaba metiendo en un callejón sin salida.
Si hubiera sabido que venía Bun, probablemente habría probado Zig, pero por desgracia (todavía) no podía ver el futuro. Así que, a falta de una opción más convincente, me quedé con un mes extra de Go, con la idea de que tendría que repetir en algún momento más adelante en el año.
Analytical April
Abril giró en torno a los lenguajes populares en la ciencia de datos. Python lo conocía demasiado bien, y R lo usé en una clase de estadística en la universidad (y no me gustó), así que decidí probar Julia.
Disfruté usándolo, pero sobre todo porque se parecía mucho a Python. Era un poco desconcertante, como ser estadounidense en Canadá. Todo se siente muy familiar, pero está un poco fuera de lugar de una forma difícil de precisar. De repente, alguien te ofrece una moneda de 2 dólares (o una función que está realmente bien pensada para hacer cálculos con matrices) y te das cuenta de que ya no estás en Kansas.
Lo que más me llamó la atención fue el sistema de tipos de Julia. Se anotaba (de forma opcional) como el de Python, pero tenía comprobaciones en tiempo de ejecución para asegurar que los argumentos coincidieran con sus tipos declarados. Creo que el sistema de Python logra el equilibrio justo entre integrarse con las herramientas y no estorbarte, pero admito que los errores en tiempo de ejecución de Julia para funciones mal tipadas también eran útiles.
En definitiva, Julia era interesante, pero no creo que lo necesite en el futuro.
Mindshifting May
Mayo insistió en eso de «probar algo nuevo» al destacar lenguajes que hacen cosas muy poco habituales. Aproveché para probar el siempre popular Rust. Tengo que decir que entiendo el hype.
Aunque el famoso borrow checker necesita su tiempo de adaptación, me gustó cómo me obligaba a pensar con más cuidado en mis programas. El compilador era ciertamente estricto, pero los mensajes de error hacían muchísimo más que ayudarme a corregir problemas. No diré que fui especialmente productivo en mi primera semana, pero siento que al menos puedo ver la cima de la curva de aprendizaje.
cargo, el gestor de paquetes de Rust, también merece una mención especial. Aunque no instalé ningún paquete de terceros, sus funciones de compilación, pruebas y formateo eran geniales. Lo mismo digo de su extensión para VSCode, que tenía todas las comodidades que esperaría de un lenguaje de tipado estático como Rust. Una buena experiencia de desarrollo realmente marca la diferencia.
Aunque a nivel de implementación son muy distintos, Rust se sentía parecido a Go en cuanto a para qué los usaría: hacer que los programas se ejecuten muy rápido. Muchas herramientas de lenguajes que uso habitualmente están empezando a pasarse a Rust por sus características de rendimiento, así que espero verlo más en el futuro (aunque yo no escriba Rust).
Summer of Sexps (June)
Junio fue el mes de las S-expressions, una forma sintáctica común en los Lisp. Elegí Clojure, un lenguaje funcional que se ejecuta en la JVM.
Había escrito un poco de Clojure hace muchos años. Acababa de salir de la escuela y me convertí en el único responsable de un script diario crítico para el negocio en mi primer trabajo. Sobra decir que fue una época complicada. Tenía curiosidad por ver si, ahora que era mayor y más sabio, resultaba más accesible.
Me alegra informar que sí lo era. La experiencia funcional de febrero me ayudó a pensar de forma recursiva, y la sintaxis no era tan mala cuando te ponías con ella. Su interoperabilidad con la JVM también sería útil si lo usara en un proyecto más grande.
No me imagino usando Clojure para nada cuando hay alternativas disponibles, pero no fue una experiencia del todo desagradable.
Misión secundaria: ¡The Universal Test Runner!
Durante años he usado una pequeña función de bash para ejecutar las pruebas unitarias del directorio actual. A medida que trabajaba con todos estos lenguajes nuevos, me encontré añadiéndole líneas por comodidad; recordar que había que ejecutar t era mucho más fácil que volver a aprender una y otra vez el comando de pruebas específico de cada lenguaje.
Como la lógica que necesitaba superó mi nivel de comodidad con bash, le dediqué un tiempo en junio y convertí el proyecto en algo propio: el Universal Test Runner.
Lo compartí en el foro de Exercism y tuvo una buena acogida. Les gustó tanto que decidimos incorporar una funcionalidad similar en la propia CLI de Exercism (que está escrita en Go, un tema que, por suerte, acababa de repasar). Así que durante la segunda mitad del año pude ejecutar exercism test para correr el conjunto de pruebas del lenguaje de ese mes (un comando que el Universal Test Runner admite de forma nativa).
Si quieres saber más sobre el proceso, escribí sobre él con mucho más detalle cuando se lanzó.
En fin, ¡sigamos!
Jurassic July
Julio estuvo dedicado a los lenguajes antiguos. La oferta de este mes era bastante escasa en cuanto a utilidad práctica. Empecé con el venerable COBOL, ya que había oído que todavía ejecuta mucha infraestructura crítica. Pero, con una boda a principios de agosto encima, no tenía la capacidad para sentarme a aprender un lenguaje tan distinto para mí. Así que, en su lugar, me pasé a Visual Basic como la opción que menos mala pinta tenía.
No hay mucho que decir aquí. El lenguaje parecía un poco verboso, pero bastante fácil de usar. Según tengo entendido, en realidad estaba pensado para el desarrollo de interfaces en Windows, así que hacer pequeños ejercicios hace difícil formarse una buena idea de todo el conjunto.
Appy August
Agosto estuvo inundado de lenguajes para crear aplicaciones. Como era de esperar, este mes había muchas opciones. Me decidí por Swift. Como alguien que usa muchos productos de Apple, su lenguaje hecho a medida es bastante relevante para mí. No era del todo nuevo para mí: en 2016 publiqué una única app para iOS escrita puramente en Swift. Pero no había tocado el lenguaje desde entonces y ha evolucionado mucho, así que pensé que igual contaba.
Me sorprendió gratamente lo fácil que era trabajar con él. A diferencia de muchos de los otros lenguajes de esta lista, Swift es bastante nuevo. Se lanzó por primera vez en 2014 y claramente se ha beneficiado de las lecciones del diseño moderno de lenguajes. Tiene un gestor de paquetes oficial, encadenamiento opcional, funciones de primera clase e interpolación de strings sensata. Se sentía ergonómico de leer y escribir, incluso sin usar Xcode.
Dicho todo esto, Swift es sobre todo útil en el contexto de apps para plataformas de Apple, que actualmente no desarrollo. Aunque funcionó bien para los ejercicios, no creo que vuelva a él pronto. ¡Eso sí, me encanta poder escribirlo en mi iPad!
Slimline September
Septiembre exploró lenguajes muy concisos o pequeños. Me decidí por jq, una herramienta que he usado y adorado durante años.
Sin embargo, siempre lo había considerado solo una herramienta para trabajar con JSON, no un lenguaje de programación de propósito general. Me sorprendió gratamente ver que tiene todo lo habitual (funciones, variables, bucles, etc.), así que pude escribir programas bastante complejos:
# input: { "series": "1", "sliceLength": 1 }
. as {series: $series, sliceLength: $sliceLength} |
if
$series == "" then
"series cannot be empty" | halt_error
elif $sliceLength > ($series | length) then
"slice length cannot be greater than series length" | halt_error
elif $sliceLength == 0 then
"slice length cannot be zero" | halt_error
elif $sliceLength < 0 then
"slice length cannot be negative" | halt_error
else
.
end
| [range(0; $series | length)]
| map($series[. : . + $sliceLength])
| map(select(. | length == $sliceLength))
Fue divertido probar todas las funciones de jq que nunca había necesitado para transformaciones de datos simples. Aunque las herramientas aquí eran algo escasas (sin integración con el editor, etc.), entender mejor la amplitud de la funcionalidad de jq valió la pena.
edición: DJ Adams en Mastodon me dio a conocer el proyecto jq-lsp y su correspondiente plugin para VSCode. Esta vez me lo perdí, pero lo revisaré en el futuro.
Object Oriented October
Octubre profundizó en los lenguajes orientados a objetos. Tengo debilidad por los diseños orientados a objetos, que reflejan de cerca cómo visualizo los programas en mi cabeza. Me decidí por Ruby, que puede sonar como una elección extraña.
Trabajo en Stripe, hogar de la base de código Ruby más grande del mundo. ¿Seguro que no contaría como un lenguaje «desconocido»? Si bien todo eso es cierto, nuestro monolito de Ruby se siente muy alejado del Ruby «estándar»: todo se verifica con tipos usando Sorbet, hay mucha generación de código y hacemos mucha magia para que todo funcione en conjunto y escale. Aunque el Ruby de dentro y de fuera de Stripe es en última instancia el mismo lenguaje, trabajar a escalas tan distintas da experiencias muy diferentes; quería saber cómo era la vida fuera (en los años desde que había usado Ruby intensamente).
En general, ¡fue bueno! Ruby en sí es genial y cita la «felicidad del programador» como uno de sus objetivos principales, algo que resonó conmigo. Me gusta lo seguido que puedo adivinar el nombre de funciones de la biblioteca estándar que nunca he usado. Me gusta lo fácil que es construir código funcional y lo ergonómica y expresiva que es la sintaxis.
Dicho esto, me sorprendió lo atrasadas que estaban las herramientas de desarrollo en comparación con Python. Quizá me tienen mal acostumbrado, pero tener sugerencias de tipos en el editor y un análisis estático y un formateo rapidísimos es más importante para mí de lo que pensaba. Para un lenguaje tan popular como lo fue Ruby en su mejor momento, me sorprendió lo atrasado que se sentía en ese aspecto.3 Tampoco me acostumbré del todo a los paréntesis opcionales en las llamadas a funciones, lo que hacía menos directo pasar funciones como argumentos.
Ruby sigue siendo un gran lenguaje y seguiré usándolo en el trabajo, pero no hace nada por mí que Python no haga, al menos por ahora.
Nibbly November
Noviembre fue el mes más difícil hasta ahora: los lenguajes de ensamblador. Aunque ya no es común escribirlos a mano, es un tema útil e interesante que conviene conocer. Elegí WebAssembly por su importancia para la web moderna y futura. Aunque normalmente se usa como objetivo de compilación (y no es algo que se escriba a mano), existe herramienta para los sickos que hay por ahí.
Me sentí inesperadamente bien preparado para este mes. La sintaxis se parecía a la de Clojure y la estructura del lenguaje me recordaba a TIS-100 de Zachtronics. Disfruté de manera extraña tener que empezar desde cero para cada operación; tenía su encanto. Odiaría tener que hacer algo de verdad de esta manera, pero mientras tanto fue una curiosidad divertida. Con comentarios generosos, logré escribir algo casi legible:
(module
(func (export "eggCount") (param $number i32) (result i32)
(local $res i32) ;; result
(local $remainder i32) ;; loop counter
(loop $loop
;; $res =
(local.set $res
;; $res +
(i32.add
(local.get $res)
;; $number % 2
(i32.rem_u
(local.get $number)
(i32.const 2)
)
)
)
;; $number //= 2
;; (keep on stack)
(local.tee $number
(i32.div_u
(local.get $number)
(i32.const 2)
)
)
;; this will keep looping until remainder is 0
br_if $loop
)
local.get $res
)
)
El mayor obstáculo fue la falta de documentación y recursos. Era difícil incluso saber qué funciones globales había disponibles. Pero dado que en realidad no voy a usar esto, una vez que arranqué no me molestó demasiado.
Diciembre cerró el año con lenguajes que no encajaban en otras categorías. Como había repetido en marzo, necesitaba completar dos lenguajes este mes.
Empecé con Wren. Creado por Bob Nystrom, famoso, entre otras cosas, por Crafting Interpreters. Me cautivó su atención al detalle, su pequeño tamaño y su diseño de arriba hacia abajo; todo parece muy bien pensado. Ese nivel de cuidado se nota en los detalles de las reglas de ámbito de variables y de privacidad. Su compilador es pequeño y tiene muchísimos comentarios, así que es un gran recurso de aprendizaje si te interesan las implementaciones de lenguajes.
Wren está un poco verde y parece estar mayormente abandonado, pero creo que está bien para un lenguaje de juguete. Nadie se acerca a esto esperando que esté listo para producción. Sin duda hay espacio en el mundo para lenguajes que no son para producción.
Además: Lua
Mi segunda elección este mes fue Lua. A diferencia de Wren, es increíblemente práctico. Su facilidad para integrarse hace que aparezca en muchos lugares, como el scripting de Redis y los mods de Factorio. El modelo de objetos necesitó un poco de adaptación, pero veo cómo podría ser productivo rápidamente. Rápidamente me acostumbré a las tablas como estructura que sirve para todo. Las herramientas eran buenas: el gestor de paquetes funcionaba sin configuración y la extensión de VSCode admitía anotaciones de tipos basadas en comentarios sin complicaciones.
Aunque no tengo nada para lo que necesite Lua de inmediato, es otra gran herramienta que tener a mano por su uso tan extendido.
Para cerrar

Disfruté este recorrido por los lenguajes más de lo que esperaba. No solo aprendí nuevas habilidades prácticas, sino que siento que amplié mucho mis horizontes.
En cuanto a lo que sigue, creo que será aprender mucho más de Rust. Su importancia en el panorama de las herramientas de desarrollo es evidente a estas alturas, y quiero asegurarme de poder leer y contribuir a las cosas en las que confío.
No tengo un entregable concreto en mente, pero tengo todo el libro de Rust por leer, un curso de Rust para desarrolladores de JS que me reembolsaron hace un año, y un track completo de Exercism por terminar. Me gustaría contribuir a al menos un proyecto de código abierto (probablemente Just, un programa que se volvió uno de mis favoritos), pero veremos a dónde me lleva el año.
Hasta entonces, ¡felices fiestas y que tengas un buen resto de 2023!
-
¿¿Las variables sin usar son un error del compilador?? O sea, por favor ↩
-
En realidad probé C++ primero (que no había escrito desde la universidad). Simplemente no era divertido, así que lo dejé ↩
-
Esta es otra forma en que el Ruby «real» difiere de mi experiencia dentro de Stripe, así que me alegra haberlo probado de las dos maneras ↩