La perlificación de Python

You know, FOX turned into a hardcore sex channel so gradually I didn’t even notice

Marge Simpson, Los Simpson

Recientemente ha salido Python 3.7, con interesantes novedades. También han salido los primeros artículos hablando de las novedades que podrá traer Python 3.8. Como muchos ya conoceréis, y si no es así explico, Python funciona a base de PEPs (Python Enhancement Proposal). Cualquier persona puede abrir un PEP, que es un documento que describe la funcionalidad que se quiere añadir/modificar/eliminar. Estas PEPs se discuten y finalmente Guido, creador de Python, las aprueba y se codifican.

Dentro de las PEP relacionadas con Python 3.8 hay algunas bastante controvertidas que han hecho saltar la voz de alarma. No ha faltado gente que ha opinado que cada vez Python se parece más a Perl. Este proceso habría empezado con Python 3 pero se habría ido haciendo más evidente hasta llegar a hoy. Cada vez con más sintaxis poco utilizada, con más elementos, más cómodo de escribir para el experimentado aunque menos legible si no dominas el lenguaje.

Y resulta curioso, porque Python es en parte una respuesta a la excesiva complejidad que podían tener los programas hechos en Perl. Su popularidad se debe a que es fácil de aprender y eso parece que ya no está tan claro.

Con la introducción de operadores como := o ?? o anotaciones como @dataclass se va, en cierta medida, perdiendo el espíritu original de Python. Y es cierto que otros lenguajes tienen algo similar, pero precisamente Python había sido muy selecto en incluir un conjunto bastante reducido de características, que todo el mundo pudiese dominar. Al final se sacrifica legibilidad y facilidad de aprendizaje por una ergonomía que beneficia a unos pocos en unos casos concretos.

Lenguajes de programación barrocos

Universidad de Valladolid, ejemplo de barroco civil. Foto: https://artevalladolid.blogspot.com

Python lleva un tiempo entrando en un proceso de perlificación pero en mi opinión no es el único lenguaje que ha entrado en una espiral parecida. Cada vez más lenguajes han pasado del renacimiento, donde se buscaba la consistencia, la simetría, la sencillez sin perder la funcionalidad, hacia el barroco, donde los lenguajes son más recargados, con más elementos sintácticos, que cubren mejor casos concretos, pero que de por sí no son tan esenciales, no cambian aspectos fundamentales del lenguaje y normalmente introducen diversas formas de hacer algo en un mismo lenguaje.

Veamos más ejemplos: en C++20 se propuso añadir funcionalidad de dibujado 2D a la librería estándar (propuesta que fue rechazada en una historia bastante larga para este post) y se han propuesto conceptos, módulos, comparación de tres vías, reflexión, metaclases,… En C# 8.0 se han propuesto también bastantes cosas como records, tipos non-nullable, interfaces con métodos ya implementados (traits) y rangos. Y eso sin contar con las características que estos dos lenguajes ya tienen, que son bastante más extensos que Python.

Retablo lateral de la Iglesia de San Miguel y San Julián (Valladolid). Barroco puro. Foto: https://commons.wikimedia.org/wiki/File:San_Miguel_-_retablo_relicario.jpg

Hay un horror vacui, horror al vacío, a funcionalidades. Siempre se añade y casi nunca se elimina. ¿Pero es realmente necesario? Es evidente que durante mucho tiempo, los lenguajes evolucionaban de forma muy lenta y muchos de los cambios que han hecho eran necesarios. Desde hace unos años, se ha aumentado la velocidad de los cambios, pero esto no puede seguir así eternamente, porque el ritmo que llevan muchas veces es superior al de los avances en lenguajes de programación y la retrocompatibilidad impide ir quitando cosas al mismo ritmo que se añaden. De este modo, todos los lenguajes que entran en esta espiral crecen y crecen. No se llegan a pulir, simplemente crecen.

La perfección no se alcanza cuando no hay nada más que añadir, sino cuando no hay nada más que quitar

Antoine de SaintExupéry

Uno podría comparar esto con lenguajes naturales, como el español o el inglés. En estos idiomas, pese a existir reglas, existen numerosas excepciones. Es posible que lenguajes como Python se estén viendo influenciados por las mismas mecánicas humanas que rigen los lenguajes naturales y que han hecho que existan excepciones. Tendría bastante sentido que ocurriese así. Pero personalmente, me gustaría que aprender Python no costase tanto como aprender alemán o francés.

Los procesos comunitarios

Para mí, gran parte de esta sobrecarga viene dada por los procesos comunitarios. En un proceso comunitario como PEP, comité de C++ o similares es mucho más fácil añadir que eliminar. En C++ la situación ha llegado a un punto en el que Bjarne Stroustrup, creador de C++, ha pedido que se relajen con las propuestas en Remember the Vasa!, en honor a un bonito barco sueco que se hundió por exceso de carga. No tanto por su peso, sino por su disposición y las reformas que hubo que hacer para que todo encajase.

El Vasa fue recuperado después de su naufragio y se expone en Estocolmo. Foto: https://rachelannsblog.wordpress.com/2016/08/03/set-sail-set-at-the-bottom-of-the-sea/

Es por ello que las personas encargadas de elegir que se añade al lenguaje o no deben de ser muy conscientes de lo que supone, ya que una vez se introduzca, va a ser casi imposible eliminarlo.

No estoy en contra de añadir nuevas características (¡al contrario!) pero se debe respetar la visión de conjunto del lenguaje, que todo cuadre y esté cohesionado. No siempre tener más es mejor.

¿Te ha gustado el artículo?

Si es así, puedes ayudar al blog. Dentro de unos días es el Amazon Prime Day. Como muchos de vosotros seguro que os compraréis algo, no quiero dejar la oportunidad de deciros que este blog tiene enlace de referidos y que por cada cosa que compréis con el enlace, me llevo una pequeña parte (a vosotros no os va a costar más caro).

Enlace Amazon.es

Será muy bien recibido

 

4 opiniones en “La perlificación de Python”

  1. Estoy totalmente de acuerdo, pero también entiendo (o quiero creer) que los lenguajes de programación evolucionan como los lenguajes naturales. Cada vez más gente los usa, cada vez más gente ve sus “carencias”, y cada vez más gente propone cosas que les gustaría que estuvieran. Los integradores ven que esas cosas proporcionan mejoras (aunque sean pequeñas) y… adelante.

    Cierto es también que quitarlas es complejísimo: seguro que hay muchas aplicaciones que usan esa característica y retocar toda esa base de código es demasiado costoso (aunque se debería hacer, claro).

    Y ya que estamos: ¿qué te parece D dlang.org ? Es otro de esos lenguajes que se hincha a características y que, hasta el momento, parece que son coherentes (¿necesarias?). Al menos a mí es el lenguaje que más me gusta en estos momentos.

    1. No conozco mucho sobre D así que no puedo opinar mucho al respecto, aunque desde fuera la impresión que me da es que es bastante bueno… y ya. Y eso no es suficiente para garantizar una adopción generalizada. Porque sus alternativas también son suficientemente buenas y necesitan un plus para dar un salto (que por ejemplo puede aportar Rust que en parte cambia los esquemas de C++). Es como lo de UNIX y Plan9, Plan9 es mejor que UNIX pero UNIX ya era suficientemente bueno, así que poca gente migró a Plan9.

  2. Excelente artículo y aun mejor reflexión.

    Considero que conozco lo bastante de Python para que me haga cierta «gracia», por decirlo de algún modo, que se use ahora en algunos libros introductorios actuales de ciencias de la computación, no porque considere que sea una elección inadecuada, sino porque Python suele usarse como alternativa a lo que suele denominarse como pseudocódigo, usandose en su forma más simple y sencilla, tanto que casi se siente el «Zen de Python» haciendo honor a su nombre… hasta que el estudiante de turno, después de terminar el libro en cuestión, al que han despertado su curiosidad por este lenguaje empieza a buscar en la documentación oficial y otros libros más avanzados sobre Python y cuando empieza a encontrarse con algo más de «chatarra sintáctica» que incluso alguna de estas barrocas construcciones sintácticas, que esconden también complejas semánticas como los decoradores (y los decoradores de esos decoradores, que decoran otros decoradores… y así at infinitum) pueda considerarse dulce y llamarlo «azucar sintáctico» pero que, por muy dulce que sean, generalmente suele ser más «turrón duro» que no a todos les gusta masticar, sobre todo porque originalmente creían por estos libros que, si acaso, se trataba de «turrón blando».

    En este sentido, llevo un tiempo debatiendo sobre Go y Rust. Go, a pesar de las críticas negativas que a veces se le hace a una de sus virtudes, la simplicidad, me parece que es de los pocos lenguajes que intentan evitar esa «perlificación» de la que hablas. Por su parte Rust me parece un lenguaje interesante que parece haber tomado lo mejor de muchos otros lenguajes y creando una combinación muy atractiva y fresca. El problema con Rust es que para disponer de todo esto su sintaxis y semántica es bastante más complicada, al menos a primera vista, que Go, y, cuando se ve el código de proyectos complejos, no puedo evitar esa sensación de que Rust ya viene con «perlificación» de serie.

    Puesto has escrito varios artículos que han conformado el interesante tutorial de Rust que ofreces en tu blog ¿Crees que Rust peca de lo mismo que C++ o de Python en la actualidad? ¿Que opinión te merece Go?

    Por último, quiero expresarte mi agradecimiento tanto por tus artículos como por tu blog en general, pues son de los pocos en español que tratan temas tan diversos e interesantes en el mundo de la programación de software y las ciencias de la computación.

    1. Hola, gracias por tu comentario, ha sido muy agradable leerlo.

      Rust ciertamente es un lenguaje bastante extenso y eso que es de los “nuevos”. No obstante, en muchos casos es algo necesario e impuesto por las condiciones que se han propuesto que cumpla el lenguaje. Por supuesto que es más sencillo tener un solo tipo de punteros y no tener que preocuparse por las diferencias entre ellos, pero ahí pierdes la ventaja de la seguridad. Y como tampoco queremos perder rendimiento a mansalva, tienen que existir punteros que no garanticen tanta seguridad (no sean seguros de forma concurrente por ejemplo) pero no tengan tanto impacto de rendimiento.

      Creo que al ser una necesidad, esa perlificación tiene menor importancia. Python trabaja a más alto nivel, así que es más grave. Por otro lado dos cosas: 1) en Rust apenas hay varias formas de hacer las cosas, aunque hay bastante azúcar sintáctico que no se ve (como las derreferenciaciones encadenadas) que en este caso hacen que el código sea más limpio y 2) Rust ha rechazado incorporar elementos de todos los paradigmas posibles, al menos de momento seguirá con su particular estilo.

      Tengo miedo de que pueda suceder lo mismo en un futuro, se han sentado precedentes de añadir azúcar sintáctico en cosas como el quick-fail, que aunque admito que es muy útil y lo uso a diario, ya oculta un poco el funcionamiento real del lenguaje. Posiblemente cuando se añada soporte a programación asíncrona llegue algo similar. Lo bueno es que hace poco se eliminó un azúcar, obligando a usar una palabra reservada cuando queríamos usar un tipo con cierto significado, (dyn fue la nueva palabra para sustituir algo que antes se hacía solo).

      Respecto a Go, no lo he usado. No me ha llamado la atención. Siempre me ha parecido de juguete comparado con alternativas más modernas. Parece un C hecho de forma distinta, pero sin nada especialmente novedoso más que un manejo de la concurrencia sencillo (pero en el fondo, tampoco nada del otro mundo).

      Saludos!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *