Sobre Thin


Motivación

La pregunta fundamental que da origen al proyecto -que lejos de ser exclusiva está detrás de muchas iniciativas en materia de desarrollo de software- es qué características tendría el lenguaje ideal para programar.

Una primer aproximación es la constatación de que en el ambiente profesional hay grandes coincidencias en las nociones conceptuales de los lenguajes y sus construcciones semánticas que los lenguajes deberían tener y que los principales puntos de discrepancia están en los detalles sintácticos y cuestiones de forma. Por ejemplo, hay a quienes les gusta usar llaves para escribir el código y a quienes les resulta muy invasivas, incómodas o poco estéticas para escribir, mientras que otros quieren tener cierta herramienta pero es incompatible con tal otra por razones de sintaxis o por cómo podía ser escrita o no en el lenguaje.

Hay un montón de situaciones o construcciones incómodas a las que conducen los lenguajes hoy y para las cuales no existe realmente una buena forma de resolverlo o no se encuentra un lenguaje que lo resuelva. Por ejemplo, no toda la gente tabule igual o elije las mismas preferencias para mostrar, que es algo que generalmente piden los lenguajes actuales. Cada desarrollador quiere que el resto lo haga como él, pero en realidad se termina llegando a que todos los que participan de un mismo proyecto se pongan de acuerdo mínimamente con un conjunto de reglas. Si el IDE soporta alguna forma de auto-aplicación o validación sobre estas reglas, mucho mejor, pero en los lenguajes nuevos mayoritariamente no sucede, ya sea porque son muy dinámicos u otros motivos. También hay ciertas construcciones que los lenguajes incluyen de forma recurrente y que el programador o bien se siente incómodo con ellas o bien las necesita pero una vez que las utiliza se empiezan a generar efectos contraproducentes. Un ejemplo de esto son la metainformación o los comentarios: un código que está lleno de comentarios es muy difícil de leer y no poderlos comentar o no poner el javadoc o no poner la metadata, termina generando que el IDE no se puede integrar, entonces uno quiere que la metadata esté ahí pero no esté ahí.

Por otra parte, a veces los lenguajes toman para sí las mejores palabras reservadas y eso hace que sea difícil integrar las mismas abstracciones que usa el cliente en el lenguaje. Por ejemplo, si el cliente en el dominio quisiera usar la palabra “clase” para algo, en la mayoría de los lenguajes resulta imposible generar ese concepto en esos términos porque es una palabra reservada y en cambio hay que empezar a poner alias con los que el cliente no está familiarizado y de esta manera se empieza a distanciar el código de lo que el dominio trabaja. También, muchas veces desde un lenguaje se extrañan los features sintácticos de otro. Uno tiende a elegir un lenguaje en base a sus conceptos y a las herramientas que ofrece, mientras que la sintaxis es un aspecto secundario. La cuestión es que quien diseña un lenguaje determina ambas: elige la combinación de herramientas semánticas y a la vez elige la combinación de features sintácticos sobre cómo expresar esas herramientas semánticas. Difícilmente la persona elija exactamente la combinación que cada profesional de sistemas quisiera tener. Por ejemplo, a alguien le puede gustar el lenguaje Ruby por las abstracciones que tiene, por las herramientas o por el mecanismo de open class, y sin embargo le parece detestable tener que utilizar la palabra “end” en todos lados y quedar sujeto a un código más verboso; entonces, al no poder pretender que haya un lenguaje a medida para su propia combinación de sintaxis-semántica se resigna a utilizar lo que hay.

También hay otros motivos que no parten de constatar problemas, sino que surgen como posibilidades creativas de facilitar la tarea de desarrollo o brindar alternativas. Por ejemplo, un profesional podría querer que las herramientas fueran más inteligentes o que haya menos procesos redundantes, algo que pasa cuando uno usa un IDE es que se está todo el tiempo reconstruyendo o recompilando algo hasta llevar un AST hasta cierto punto para poder luego pensar sobre él o uno podría querer reutilizar ciertas nociones que escribe como que la documentación que uno le pone al método muchas veces describe lo que el método debería hacer y muchas veces, si vos ves los test, esas nociones están reescritas en otro lado. Sería bueno si uno pudiera encontrar una forma de compatibilizar todo eso.

Fundamentos

Ningún lenguaje, hasta ahora, provee la forma de trabajar sobre estas cuestiones, en gran medida, porque todos los lenguajes que existen hoy están basados en texto.

El texto es muy importante porque es la forma como se construye software en la actualidad: la manera en la que se puede escribir hoy un algoritmo es tipeándolo. Hay una idea que tiene el desarrollador que la representa escribiendo el código y guardándolo en un archivo. Pero aún así, no hay ninguna buena razón para que el lenguaje esté basado en estos archivos de escritura en lugar de concentrarse en las ideas que estos archivos querían representar.

Con el objetivo de mejorar en muchos aspectos las herramientas de desarrollo, aplicar mejor los conceptos y flexibilizar al máximo los lenguajes, la clave de un “lenguaje delgado” es que en lugar de centrarse y guardar el texto, guardar las ideas que se quisieron escribir.

La convicción que sustenta el trabajo es que los lenguajes podrían sacar mucho beneficio de centrarse en la idea que se quiere transmitir con ese código antes que en las palabras puntuales que fueron utilizadas para escribirlo.

En el ambiente, se suele utilizar el término de “Grasas Sintacticas” o “Syntactic Fat” para referirse básicamente al conjunto de todas las cuestiones sintácticas, incluyendo lo que son palabras reservadas, la forma de escribir, la forma de tabular, el coloreado de las palabras y toda noción que no sea ni metainformación ni parte de la sintaxis abstracta.

Existen ventajas que podríamos obtener que incluyen tener múltiples formas de visualizar la misma cosa, y eso al mismo tiempo hace que todo lo que no forme parte de la sintaxis abstracta no necesite estar soportado en el lenguaje por lo tanto cualquier cosa podría estar soportado en el lenguaje más allá de lo que está, un ejemplo concreto de esto son los comentarios, el lenguaje no tiene porque definir como soportar los comentarios, porque los comentarios son simplemente metadata. No necesito tener una forma de escribirlo necesariamente, o un carácter reservado para todo lo que esté entre estos dos pares de caracteres es un comentario, yo podría directamente introducir un comentario a través del IDE y que eso se guarde directamente atrás en el AST y eso poder verlo o no verlo cuando quiera, no tiene porque formar parte del texto que define mi programa y eso me permite al mismo tiempo poder agregar varios niveles de flexibilidad en cómo lo hago, por ejemplo yo podría poner dentro de un contexto a un comentario, que es algo que hoy en día no se puede, yo pongo el comentario arriba de la palabra que yo creo que es interesante pero tal vez yo quiero poner un comentario para una cierta porción particular del código ponerle un principio y un fin o visualizarlo de cierta forma o poner ciertas restricciones a como quiero que se vea, como querer que esto esté subrayado en azul y cuando le paso el mouse por arriba que se visualice, o querer poder conectar este comentario que acabo de poner o extraerlo de otro lugar como por ejemplo la descripción de un test. Todo lo que sea metainformación como: comentarios, annotations o cosas similares soportadas por cualquier lenguaje podría ser más o menos invasiva dependiendo de lo que quiero en cada momento, ni siquiera tengo que poder definirlo para una herramienta en particular.

Ideas centrales, Características, Objetivos, Utilidad en industria y ambientes educativos

Como comparación rápida entre un lenguaje actual y un lenguaje delgado se puede afirmar que un lenguaje actual está basado en lo que está escrito mientras que un lenguaje Thin estaría basado en el significado de aquello que se escribe, de lo que se quiere que el programa haga. En otras palabras, el lenguaje actual permite menos personalización o está atado a ciertas restricciones que un lenguaje Thin podría no tener, sería mucho más flexible. Los lenguajes actuales necesitan definir dentro de su core o de lo que es el lenguaje, la forma de manejar la “Grasa Sintáctica” y la manera de ubicar eso en las fuentes y de la manera de persistirlo, y de descartarlo o no, mientras que un lenguaje delgado reconstruiría la “Grasa Sintáctica” es acorde a cada persona y cada quien podría ver las cosas como quiera independientemente del lenguaje.

Básicamente lo que propone es persistir y trabajar sobre la sintaxis abstracta, si se quiere, en lugar de la sintaxis concreta. En lugar de tomar lo que la persona escribió exactamente, guardarnos, por ejemplo, el AST, o guardar cualquier construcción de la cual se pueda extraer directamente la intención de lo que estaba escrito y descartar todo lo que sea accesorio a la idea. Es posible descartar las palabras específicas que se usaron, la tabulación, las elecciones de un montón de preferencias de usuario con respecto a “dónde hay ” o “¿Cómo está escrito algo?” y quedarnos solamente con la esencia del programa. La idea de Thin es que esta preferencia sobre cómo escribir pueda ser configurada para cada persona, para cada individuo, y a partir de esta esencia (podemos empezar a hablar de AST para simplificar), a partir del AST guardado se reconstruya el código cómo la persona lo hubiera escrito, ese es el objetivo principal de Thin. Si podemos reescribir el código como la persona lo hubiera escrito podemos directamente guardar la idea atrás del código y todos podríamos ver el código de cualquier persona como lo hubiéramos escrito nosotros mismos, con nuestras propias preferencias, con nuestra propia forma de encararlo.

Esto implica en realidad un cambio bastante más profundo de lo que podría parecer al principio porque es redefinir la idea no solo de lo que es un programa sino que de lo que es un lenguaje. Hoy en día entendemos un lenguaje como una combinación de sintaxis y semántica, un montón de herramientas de las cuales tengo una forma de escribirlo pero, si nos paramos en la idea que propone Thin, en realidad solo el conjunto de herramientas es lo que compone el lenguaje y la sintaxis es algo que podría perfectamente ser configurable, siempre con ciertas limitaciones, pero para cada persona en particular. Entonces, si uno dijera “bueno, vamos a hacer una versión Thin de Java”, esta versión lo que tendría son las herramientas que Java provee, su sistema de clases, su forma de comunicar los objetos, sus construcciones reservadas (como el “if”, el “for”) su forma de definir metadata, pero no tendría ninguno de los detalles sintácticos, no habría dentro de la definición de Java de Thin las “llaves” o con qué caracter se escriben los comentarios o cuál es la palabra clave reservada para el “if”. Todas esas cosas podrían ser elegidas y, por supuesto, cualquier cosa referida a, por ejemplo, cómo te gustaría tabularlo, cómo te gustaría estructurar tu código. Para esto es fuertemente necesario trabajar sobre un IDE o al menos una herramienta de edición que sea suficientemente inteligente como para poder deconstruir y reconstruir tu código. No hay demasiada vuelta. Sin embargo, nosotros creemos que para programar es necesario tener una herramienta inteligente, consideramos que programar en un editor de texto es una mala práctica. También entendemos que los editores de texto son cada vez más evolucionados, entonces la línea entre lo que es un editor de texto y un IDE se desdibuja pero si lo que tu programa guarda es un AST en lugar de un texto que vos escribiste no podrías editarlo directamente con un editor de texto a menos que este tenga un plug-in que te reescriba el código en base a tus preferencias para poder trabajarlo. Lo que creemos que se obtiene a partir de esto es que, al no haber una sintaxis definida para el lenguaje, el conjunto de ideas o de herramientas que representa el lenguaje, luego puede ser reescrito de un montón de formas. Eso podría llevar a la eliminación de lenguajes redundantes, o de lenguajes que son muy similares.

Otra cosa que se desprende después de un análisis más profundo de Thin es que, sin una sintaxis que lo restrinja, no hay muchas diferencias entre las herramientas core del lenguaje y una librería que uno pueda construir y eso podría llevar a lenguajes modulares, lenguajes que, por ejemplo, usan objetos pero podrían usarlos con traits o mixins o herencias simples sola o herencias múltiple, cualquier combinación de herramientas y cualquiera de esas podría ser un módulo, cada uno podría usar la que más le guste. Ese programa luego se construiría y podría ser compatible con otro lenguaje o con otra combinación de herramientas que no necesariamente coincide con las que uno eligió. Al no tener una restricción sintáctica, el lenguaje se vuelve más fácilmente extensible y se vuelve más fácilmente interoperable con otras combinaciones de herramientas. El contraejemplo de esto, es lo que, por decir algo, pasó con Java al momento de poner Annotations. Java no tuvo que poner una palabra especial @Interface, que no era un identificador válido para mantener la retrocompatibilidad y les costó un montón de tiempo poder meterlo y, si nos fijamos en la historia, la mayoría de los lenguajes que proponen tener una retrocompatibilidad, agregar nuevas construcciones siempre es difícil porque podría haber una colisión con las abstracciones previas. Sin embargo, si siempre guardamos la AST, o sea, si siempre guardamos la construcción que queríamos hacer en lugar del texto que la producía, lo que termina pasando es que nunca hay un problema hacia atrás, porque siempre guardamos lo que queríamos decir y no las palabras que lo formaron.

Presentación de Thin en WISIT ‘15

El 19 de Septiembre presentamos Thin Languages en el WISIT, esta fue la presentación de lo que contamos en el workshop

Presentacion WISIT ‘15