Notxor tiene un blog

Defenestrando la vida

Lenguajes repelentes

2022-09-09

Hoy traigo sólo un poco de reflexión e historia de los lenguajes de programación al blog. Ya lo siento, hoy toca chapa de la fina... Y es que no he podido resistirme al título, porque me ponga como me ponga al final los lenguajes en los que programo son repelentes, o al menos yo así los llamo. Para entrar en materia con un poco más de conocimiento de causa: supongo que la mayoría sabéis qué es eso de REPL1. Esos son los lenguajes que yo llamo repelentes; bueno, también existen los lenguajes que son repelentes para mi gusto (el C++ y el Java, fundamentalmente, y que curiosamente no es ninguno REPL). Si tienes paciencia suficiente para leer este artículo, te contaré por qué me gustan algunos lenguajes y por qué no me gustan esos mismos lenguajes. El criterio es el que me sale a mí, sin ninguno más, ni más vueltas y sé que caigo en contradicciones, ya veréis que algunos lenguajes me caen bien por lo mismo que no me gusta de otros. En algunos de los lenguajes aquí desglosados, me he permitido poner un poco de código para que se vea cómo luce visualmente. En fin: no te garantizo nada, a tu discreción dejo la lectura.

Motivos, ninguno

Aprendí a programar, no sé muy bien por qué. El caso es que aprendí y lo utilizo para mis cosas. En mi ingenuidad inicial, pensé que la tecnología era algo lógico, exacto, pero me encontré amando y odiando como amo a las personas, sin un porqué concreto. Hay personas que te parecen buenas, sanas, interesantes y las amas por más aristas, pegas y defectos que la gente de tu alrededor las encuentre. Eso me pasa a mí también con los lenguajes de programación y con muchas otras cosas de la tecnología. Amar algo siempre me ha parecido raro, pero amo programar, casi tanto como conducir una moto por una carretera de montaña sin tráfico. Pensándolo ahora, quizá sea porque me concentro en una actividad que requiere toda mi atención. Sobre la moto hay quizá más adrenalina, porque también exige coordinación física y mi integridad está en juego. Sobre la programación quizá más sublime, más intelectual y, también, más reforzante intelectualmente.

Hace tiempo que no tengo un lenguaje favorito, no me merece la pena. Cuando aprendía, iba saltando de un lenguaje a otro, el último siempre era el candidato y pasé por muchos y muchas fases. Ahora los voy acumulando poco a poco, cada año o cada dos años añado alguno más a la cuenta y no veo que pueda aprender ni la mitad de los que me llaman la atención antes de morirme. Hacer una cronología exacta de cuáles aprendí primero y cuáles después se me hace complicado, porque algunos aparecen y desaparecen para volver al cabo de un tiempo. No es raro tampoco que esos lenguajes que durante el primer vistazo me parecen feos o raros, más adelante se conviertan en uno de los que amo, igual que me pasa con las personas. Así que voy a repasar estos lenguajes repelentes que me gustan.

Smalltalk

Supongo que alguno de vosotros esperaba que empezara por Lisp, por antigüedad y porque en este blog creo que no hay ni una sola línea de Smalltalk y sí cientos de Lisp. Pero en fin, os sorprenderá, pero soy así y creo que ya no cambiaré mucho.

Smalltalk fue uno de esos descubrimientos intermitentes que me apasionó durante un tiempo, pero ese enamoramiento se diluyó por la cantidad de pegas que hay que superar con él. Mi primer contacto fue con el entorno Squeak. Fue en un ámbito educativo y me gustó como herramienta, especialmente con sus Etoys que permitían de forma muy sencilla juguetear en el aula con gráficos y crear entornos de simulación sencillos. El primer contacto se quedó en el juguete. Más tarde, metido en la filosofía del lenguaje: Todo es un objeto, comencé a programar en ciclos REPL utilizando sus herramientas Transcript y Workspace.

Esto fue en una segunda mirada, en la que también descubrí las bondades de la programación TDD2 y me encontré escribiendo más código en el depurador que en el Browser. Un lenguaje hermoso, claro y con unos principios sencillos. Todo es un objeto, los condicionales y los bucles son métodos de la clase boolean, los bloques de código son objetos con los que trabaja el evaluador. Los objetos los puedes modificar sobre la marcha mientras se están ejecutando en el entorno sin que haya el más mínimo problema. Así que puedes ver cómo tus clases y tus objetos van tomando forma y ajustándolos a lo que quieres.

Sin embargo, la apariencia de Squeak es bastante infantil, se diseñó para ser utilizada en ámbitos educativos para los chavales y aunque hay de todo: entornos de virtualidad 3D como Croquet, webservers y muchos otros tipos de aplicaciones (emuladores, game engines, bases de datos), resulta un poco frustrante programar para este entorno. Crear una aplicación útil y cuando se la enseñas a alguien sólo se fija en los iconitos de colorines infantiles.

Probé otros Smalltalks, algunos profesionales, pero el entorno completo significaba muchos miles de euros y los libres son escasos. EL entorno Pharo prometía, era un derivado de Squeak con un aspecto más profesional y menos infantil. Curiosamente, eso que parecía que era lo que quería era lo que me disgustaba de Pharo. Las decisiones de diseño no iban hacia donde a mí me gustaba y no cuajó. Hacer programas para mí es sencillo, me da un poco igual el aspecto de la interfaz, normalmente suelo preferir las interfaces interactivas, tipo repelente, pero la mayoría de la gente no: quiere GUI's y botones.

Me sigue gustando Smalltalk, orientado a objetos puro, pero apenas lo utilizo actualmente. Aunque me he plantado el recuperarlo para el aula con chicos y enseñarles algo de programación con Squeak, en lugar de con el infumable scratch. No sé, lo mismo hasta aprenden a programar de verdad en lugar de arrastrar bloques uno detrás de otro a ver si encuentran el que hace lo que quieren.

Lisp

Dicen las malas lenguas que lo del REPL lo inventó Lisp y no soy quién para negarlo, teniendo en cuenta que es uno de los primeros lenguajes de programación. Este lenguaje (o alguno de sus derivados, porque incluyo aquí también Scheme) lo utilizo casi a diario.

La filosofía es bastante sencilla: todo es una lista, las listas son datos, las listas son código. Dicen, también las malas lenguas, que Lisp no es un lenguaje ideal para ningún nicho de programación, o ámbito de problemas. Sin embargo, con él se puede hacer cualquier lenguaje para cualquier ámbito de programación concreto. De hecho, las aplicaciones más exitosas que lo utilizan3 pueden ser consideradas como un Lisp disfrazado de otra cosa. Es decir, podríamos decir que Emacs es un Lisp disfrazado de editor. A estas alturas, creo que no hará falta decir que tengo miles de líneas propias de código Lisp que corren en Emacs para hacer mis cosas, desde este blog, a tomar notas, gestionar mi agenda, hacer informes.

Pero también le encuentro pegas. Especialmente a Commond Lisp, con una gestión de dependencias imposible muchas veces, cualquier aplicación que quieres pasar a alguien tiene que terminar en un contenedor con todas las librerías y algo que apenas serían algunos Kb de código termina ocupando decenas de Mb. Como en Smalltalk el problema se produce cuando quiero compartir algún programa que he hecho. A mí en mi entorno me funciona y el aspecto tampoco me preocupa demasiado. Pero hacerlo funcionar en otro entorno y con un aspecto «poco moderno» a la gente no le apetece probarlo... no puedes hacerte millonario vendiendo módulos de Emacs.

Normalmente, suelo utilizar, o mejor dicho, me gusta más, hacer programas interactivos, a los que enviarles comandos y acciones desde un entorno repelente para trabajar. Sin embargo, me gusta ver los resultados de modo más gráfico y eso es una de las ventajas de emacs-lisp, que viene con el entorno completo. Por lo tanto, lo que es lisp se me circunscribe casi exclusivamente a él. Hago mucho de mi trabajo como psicólogo desde él: anotaciones, escritos, informes, corrección de tests, seguimientos, estadísticas, agenda... en fin, que para coordinarlo todo tengo que tener, además, unas 2.000 líneas de código elisp propio, que me facilitan el trabajo rutinario. Sin embargo, no puedo compartir esas herramientas de psicólogo para el psicólogo medio con lo cual, me frustra a veces hablar de herramientas con algunos compañeros y al comentarlos cómo lo hago yo, que no me entiendan, mostrarles cómo y dado el aspecto de texto plano, lo consideren arcaico. Por eso empecé a hacer una aplicación que lo haga todo y sea capaz de hacer las cosas de manera interactiva, pero tenga también botones y ventanas... pero no podrá ser en lisp.

(defun factorial (n)
  (if (= n 0)
      1
    (* n (factorial (- n 1)))))

Clojure

La verdad es que comencé con Clojure este año. A principios de enero configuré Emacs para trabajar con este lenguaje4 y comencé a mirar un libro que se llama Clojure for the Brave and True y avancé bastante rápido. No deja de ser un lisp aunque con algunas idiosincrasias y corriendo sobre una máquina virtual de Java.

¿Me gusta Clojure? En general sí, pero leo a mucho exaltado hablando de las glorias del desarrollo repelente, —bueno REPL, ya me entendéis—, y parece que lo haya inventado Clojure hace dos semanas. Y, en el fondo, está bien, pero tampoco le veo tantas ventajas sobre el método tradicional de escribir código y probarlo (si tienes unos tests a mano para hacerlo). Que por cierto, al final es lo que hacen pero desde su propia shell. Creo que dichos exaltados deben venir del mundo «güindosero» y les daba urticaria abrir una consola de texto hasta que encontraron Clojure; si no, no lo entiendo.

La ventaja que le veo a Clojure es que tienes al alcance toda la inmensa librería de Java y puedes hacer literalmente cualquier cosa que haga la JvM con un lenguaje mucho más agradable de trabajar que el propio Java. Por tanto, su principal ventaja es que corre sobre la JVM, puedes distribuir aplicaciones jar, llamar a librerías, etc. También puede convertir el código en javascript, lo cual lo hace apto también para enmierdar webs con un montón de código innecesario para transmitir información.

La principal desventaja es... que corre sobre JVM y la carga es lenta... me gusta que haya funciones especiales para evitar las sobrecargas con las funciones tail recursive, mientras que en otros Lisp, Scheme e incluso erlang te recomiendan utilizar referencias circulares con una función auxiliar; en Clojure ya te dicen que esa función auxiliar se llama recur. A mí me sigue gustando más el llamar de nuevo a la función recursiva por su nombre, puesto que utilizar otros nombres como loop y recur, me distrae un poco de lo que hace la función, pero son gustos míos.

En resumen ¿me gusta Clojure? Sí. ¿Lo uso mucho? No. En general, si necesito un script rápido lo más a mano que tengo es bash, o incluso Python o, últimamente, Tcl/Tk, que además me permite hacer scripts con ventanitas... En fin, lo mismo dentro de poco (o nunca) se me ocurre algún proyecto donde utilizarlo.

(defn factorial-reduce [n]
  (reduce * (range 1 (inc n))))
(defn factorial-loop [n]
  (loop [x n, acum 1]
    (if (>= 1 x)
      acum
      (recur (dec x) (* x acum)))))
;; => user> (time (factorial-loop 5))
;; => "Elapsed time: 0.134864 msecs"
;; => 120
;; => user> (time (factorial-reduce 5))
;; => "Elapsed time: 0.206662 msecs"
;; => 120

No está de más echar un vistazo a los resultados anteriores de las dos versiones de la misma función (en cuanto a tiempos de ejecución me refiero).

Erlang

Otro de los lenguajes repelentes. Además el mismo que es tachado como feo por muchos y es cierto, al principio a mí también me lo pareció. Pero luego he cambiado de opinión. Lo que me enamoró de este lenguaje es su capacidad para la concurrencia. Programar con él consiste en levantar procesos que se comuniquen unos con otros incluso en distintas máquinas... lo que lo hace ideal para aplicaciones en red.

Tiene otras ventajas dada su fea sintaxis y la capacidad para deconstruir los parámetros y variables en estructuras de datos concretas, permite evitar muchas de las estructuras condicionales de otros lenguajes de programación.

Puede hacer cosas tan vistosas como un modelador 3D. O el raytracer que me entretuve en hacer en los artículos, ¿quién iba a pensar que se podía hacer un raytracer en /erlang?:

Viene también con todo un entorno de seguimiento y depuración, con sus correspondientes GUI's para que puedas apreciar mejor cómo interactúan los procesos que has creado. Puede funcionar también en modo interactivo o repelente, aunque el proceso de desarrollo habitual que uso es el tradicional de escribir código, compilar y pasar pruebas.

¿Me gusta erlang? Me encanta ¿Lo uso mucho? Pues no demasiado. Tengo algunos scripts escritos en erlang pero no es el que más utilizo.

factorial(0) -> 1;
factorial(N) when N > 0 -> N * factorial(N-1).

Tcl/Tk

Creo que este lenguaje es el gran desconocido. Se inició en la Universidad de Berkeley allá por 1988 y se desarrolló principalmente en los laboratorios de Sun a la par de Java, pero parece que no le hicieron la misma publicidad. Nació para ser embebido en otros programas, principalmente escritos en C, pero terminó también teniendo un desarrollo como entorno REPL y es famoso por su entorno gráfico Tk, que en la actualidad se encuentra también portado a otros lenguajes, además de en Tcl, está para Python, Ruby o Perl. Es multiparadigma, tanto puedes emplear POO, como programación funcional o procedural.

Por algún lado leí, que el desarrollo de Tcl/Tk parece una carrera de imitación con el desarrollo de Python, compiándose unos a otros de manera que lo que inventa uno, el otro lo incorpora al poco tiempo. No sé cuánto de verdad habrá en ello, pero es cierto que me he encontrado con una herramienta muy potente, con librerías para todo lo que necesito. Sin embargo, su sintaxis no termina de gustarme y la forma de gestionar los ámbitos de las variables, las variables globales y otros detalles, me parece un poco farragosa.

¿Me gusta Tcl/Tk? Sí ¿Lo uso mucho? Pues últimamente lo estoy usando donde antes utilizaba Python. Tiene cientos de librerías y se puede hacer de todo con él... y lo noto menos pesado que Python.

proc factorial-recur {val} {
    if {$val == 0 } {
        return 1
    } elseif {$val >= 1} {
        return [expr {$val * [factorial-recur [incr val -1]]}]
    }
}
proc factorial-loop {val} {
    set result 1
    while {$val != 1} {
        set result [expr {$result * $val}]
        set val [incr val -1]
    }
    return $result
}
# => % time {factorial 5}
# => 16 microseconds per iteration
# => % time {factorial-loop 5}
# => 13 microseconds per iteration

En el caso de Tcl/Tk se desempeña mejor el bucle que la recursión, aunque no hay mucha diferencia.

Python

Python lo aprendí mucho antes que otros de los lenguajes cuando estaba muy metido en la programación orientada a objetos, con Smalltalk y fue agradable encontrar un lenguaje donde pudiera emplearlo sin los problemas que habían empezado a molestarme en Squeak. El caso es que se convirtió en el más usado de aquellos tiempos y aún tengo algunas cosas hechas con él. Creo que era por la versión 1.8.X cuando comencé a hacerle caso.

Con el tiempo comencé a cogerle un poco de ojeriza, no por el lenguaje en sí, sino por mucho supuesto teórico que escribían cosas sobre sus maravillas, que si la introspección esto, que si la introspección aquello, que si la flexibilidad... en fin, que parecía que habían inventado el mundo, cuando muchas de esas cosas estaban implícitas en Smalltalk desde hacía décadas. Sin embargo, el lenguaje no tiene la culpa de atraer a singermornings de cualquier especie.

Hubo una época donde estuve además jugueteando con él y con un editor que se llama Leo. Lo que ocurre es que, al poco de tomarme en serio ese editor y Python, encontré tantas referencias a org-mode y Emacs en las entradas de blogs que hablaban sobre dicho editor, que me entró la curiosidad... y la curiosidad mató al gato, bueno al león. Probé Emacs y org-mode y no hubo vuelta atrás. Muchas de las cosas que utilizaba entonces en Python pasaron a estar implementadas en elisp.

¿Me gusta Python? Por supuesto ¿Lo utilizo mucho? Pues cada vez menos. En los scripts rápidos para línea de comandos está siendo sustituido en mi caja de herramientas por Tcl/Tk. Si tengo que hacer algo por red en plan cliente-servidor lo hago en erlang. Pero la mayor parte de la carga de trabajo sigue descansando en elisp y Emacs... porque algunas de las cosas que tenía implementadas en Python me las encontré ya hechas en org-mode o en otros paquetes del editor.

El futuro

No creáis que he acabado mi periplo de lenguajes, ni mucho menos. Para el futuro me estoy planteando el aprender julia. También es un lenguaje repelente, con su entorno para el REPL, quiero decir, ya sabéis. Promete además que es mucho más rápido que otros de estos lenguajes repelentes que os he nombrado por aquí. Por lo que he leído es incluso más rápido que Python con el jit activado o C#, en algunos casos incluso más que C++, según las características de algunas de las funciones del banco de pruebas, aunque en general, siempre más lento que C. Me parece que promete mucho, quizá demasiado. Cuando lo pruebe ya veremos.

Ese lenguaje me interesa, además, porque es otro de los lenguajes que suenan para uso estadístico. En este artículo no he hablado sobre R, aunque lo uso para algunas cosas, efectivamente para estadísticas. Es un lenguaje que creo que se podría utilizar para otras cosas y no sólo cálculos estadísticos, pero toda la literatura lo coloca en ese nicho y no hay forma de sacarlo del hoyo. Parece que julia está siendo utilizado también para cálculos estadísticos y en algunos ámbitos parece haber desbancado a R. Cuando lo pruebe ya veremos.

Otra de las promesas de julia es la completa integración con tipos de letra y códigos UTF. Otros lenguajes lo prometen también, pero al final hay que estar haciendo conversiones más o menos explícitas entre códigos... En fin: cuando lo pruebe ya veremos.

No he desistido tampoco de Haskell, llevo tiempo queriendo aprenderlo y van cuatro intentos. Cada intento avancé más que el anterior. Cuando creo que lo entiendo me aparece otra cosa y me pone los conceptos patas arriba. En fin, algún día conseguiré comprenderlo de verdad y ese día diré que soy programador de los de verdad y no como cualquier psicólogo con ínfulas de programador.

Conclusiones

Siento haberos dado la chapa con estas cosas, que seguramente sólo me preocupan a mí. No encuentro mi lenguaje favorito y a estas alturas tampoco creo que lo encontraré. Lo cual me hace estar más abierto a qué debo usar para según qué cosas. Cuando tienes un martillo todo te parecen clavos, pero en este caso en la caja de herramientas empieza a haber un amplio muestrario de lenguajes, con varias opciones para elegir entre los paradigmas: orientado a objetos, funcionales, procedurales.

No quiero decir que me gusten menos los lenguajes compilados, pero me gustan los lenguajes repelentes, con su línea de comandos dispuesta a hacerme caso y funcionar, sin necesidad de editar ningún fichero, ni escribir ningún programa, ni compilar nada. Pero son mis gustos.

Footnotes:

1

El ciclo de Read-Eval-Print-Loop que han venido a abreviar en REPL y que cuando lo leo deprisa me sale sin pensar «repelente».

2

Tests Driven Development o desarrollo dirigido por pruebas, que diríamos en cristiano.

3

Autocad y Emacs, por ejemplo.

4

A estas alturas la configuración de clojure la he hecho sin lsp. De hecho, ya no utilizo lsp con ningún lenguaje.

Categoría: programación emacs lisp python erlang tcl smalltalk

Comentarios

Debido a algunos ataques mailintencionados a través de la herramienta de comentarios, he decidido no proporcionar dicha opción en el Blog. Si alguien quiere comentar algo, me puede encontrar en Mastodon y en Diaspora con el nick de Notxor.

También se ha abierto un grupo en Telegram, para usuarios de esa red.

Disculpen las molestias.