39 puntos por xguru 2022-12-12 | 7 comentarios | Compartir por WhatsApp

¿Qué es un "Little Language"?

  • Los "lenguajes pequeños" son lenguajes creados con el propósito de resolver un problema específico
    → SQL, RegEx, Dhall,..
    → También se les llama DSL

¿Por qué hacen falta los lenguajes pequeños?

  • A medida que las aplicaciones se han vuelto mucho más complejas, el código fuente también ha crecido, pero además se ha vuelto más difícil de entender
  • Se complica el onboarding de nuevos empleados, ocurren errores por falta de comprensión de las dependencias y cada vez resulta más difícil gestionar los cambios en el código
  • En los últimos 10 años, las bases de código han crecido entre 100 y 500 veces
    • El kernel de Linux comenzó en 1992 con 10 mil líneas, pero 20 años después llegó a 30 millones de líneas
  • Este tipo de código no existe solo "porque haya más funciones". También porque cambió la manera en que construimos software
    • El software es como construir una pirámide: para colocar la última piedra, se necesitan muchas más piedras debajo

Superar la tendencia

  • ¿De verdad hacen falta obligatoriamente cientos de miles o millones de líneas de código para crear un sistema operativo moderno?
  • Alan Kay cuestionó esta suposición en el programa STEPS en 2006
  • Pensamos que crear un "lenguaje" adecuado para el problema que queremos resolver hace más fácil resolverlo, y permite que la solución sea más comprensible y también más pequeña

  • En STEPS crearon un lenguaje llamado Nile, y lograron implementar una funcionalidad similar a la de un renderizador Cairo de 44,000 líneas con alrededor de 300 líneas de código

¿Por qué no bastan los lenguajes de alto nivel?

  • ¿No bastaría con crear un lenguaje multipropósito de nivel aún más alto?
  • Personalmente, creo que ya llegamos a un punto de rendimientos decrecientes en la expresividad de los lenguajes de propósito general
  • ¿Cómo sería un lenguaje todavía más alto nivel? Si tomamos Python como ejemplo, ya está en un nivel tan alto que parece pseudocódigo
  • El problema de los lenguajes de propósito general es que primero tienes que traducir tu problema a un algoritmo y luego expresar ese algoritmo en el lenguaje objetivo
    • En 1986, en Programming Pearls de Jon Bentley, se invitó a Donald Knuth y Doug McIlroy a escribir un programa para contar la frecuencia de palabras. Don lo escribió a lo largo de 10 páginas en WEB, una variante de Pascal, usando estructuras de datos complejas
    • En cambio, Doug lo resolvió con una tubería Unix de 6 líneas usando tr, sort, uniq, sort, sed, etc.

Menos es más

  • El comando Unix anterior muestra otra característica de los lenguajes pequeños.
    "Lenguajes menos poderosos y runtimes más poderosos"
  • Gonzalez habla de esta tendencia en "The end of history for programming"
    • Empujar los problemas del espacio de usuario hacia problemas del runtime
      • Hacer que el programa se parezca más a una expresión matemática pura y aumentar mucho la complejidad del runtime
  • Las expresiones regulares y SQL no pueden expresar nada fuera de la búsqueda de texto y el trabajo con bases de datos, respectivamente
  • Esto contrasta con lenguajes como C, donde no existe un runtime de ese tipo y todo es expresable
  • Los lenguajes pequeños están en el extremo opuesto del espectro de poder que tiene C
    • No solo abstraen la arquitectura de la computadora, sino que además limitan los tipos de programas que se pueden expresar, por lo que por diseño son Turing-incompletos
    • Puede sonar muy restrictivo, pero abre una nueva dimensión de posibilidades para optimización y análisis estático

Análisis estático

  • Los lenguajes menos poderosos son más fáciles de razonar y pueden ofrecer garantías más fuertes que los lenguajes de propósito general
  • Por ejemplo, Dhall es un "Total Functional Programming Language" para generar archivos de configuración
    • Es decir, para eliminar el riesgo de caer en bucles infinitos, Dhall "garantiza" que los programas "(1) no fallan y (2) terminan en un tiempo finito"
    • (1) se logra evitando lanzar excepciones. Las operaciones que pueden fallar devuelven un resultado Optional (puede haber valor o no)
    • (2) se logra al no permitir definiciones recursivas
  • En otros lenguajes funcionales, la recursión es la forma básica de implementar bucles, pero en Dhall hay que depender de la función fold integrada
  • El hecho de no tener una estructura general de bucle significa que Dhall no es Turing-completo. Pero como no es un lenguaje de propósito general, no necesita serlo
  • Cuando un lenguaje es pequeño, razonar sobre él es mucho más fácil
    • Por ejemplo, en Python es difícil verificar si un programa no tiene otros efectos secundarios, pero en SQL basta con revisar si la consulta empieza con SELECT
  • En el caso de Nile, el equipo de STEPS necesitaba un depurador gráfico y por eso lo construyó, y puedes verlo directamente
    • Esto fue posible porque Nile es un lenguaje pequeño sobre el que es fácil razonar

La necesidad de velocidad

  • Los lenguajes de programación más poderosos no solo aumentan la posibilidad de errores, también pueden perjudicar el rendimiento
  • Por ejemplo, si un programa no está expresado como algoritmo, entonces el runtime puede elegir por su cuenta el algoritmo
    • Las expresiones lentas pueden reemplazarse por otras rápidas (asumiendo que se pueda demostrar que producen el mismo resultado)
  • Por ejemplo, una consulta SQL no indica cómo debe ejecutarse
    • El motor de base de datos puede decidir libremente qué plan de ejecución conviene usar
      • si usar un índice, un índice compuesto o escanear toda la tabla de la base de datos, etc.
    • Los motores de base de datos modernos también recolectan estadísticas sobre la distribución de valores de cada columna, por lo que pueden elegir al vuelo el plan de consulta estadísticamente óptimo
    • Si la consulta viniera en forma de algoritmo, esto no sería posible
  • Uno de los "ingredientes secretos" que hizo al lenguaje Nile tan conciso fue "Jitblt", un compilador Just-in-Time para renderizado gráfico
    • A través de discusiones entre STEPS y el equipo de Cairo, descubrieron que gran parte del código de Cairo se usaba para optimizar manualmente operaciones de composición de píxeles
    • En teoría, este trabajo podía delegarse a un compilador
    • Dan Amelang, del equipo de Cairo, se ofreció a implementar ese compilador, y así nació Jitblt
    • Esto significa que el trabajo de optimización del pipeline gráfico puede separarse de una descripción matemática pura de qué se va a renderizar,
      lo que permitió que Nile pudiera ejecutarse tan rápido como el código original de Cairo optimizado a mano

Small languages, Big Potential (Lenguajes pequeños, gran potencial)

  • Entonces, ¿qué pasó con STEPS? ¿Lograron crear un sistema operativo que pudiera ejecutarse con una cantidad de código tan pequeña como para imprimirse en una camiseta?
  • El resultado final de STEPS fue KSWorld
    • Un sistema operativo completo con editor de documentos y editor de hojas de cálculo integrados
    • 17,000 líneas de código
    • Es un poco largo para caber en una camiseta, pero yo lo considero un éxito
  • La creación de KSWorld muestra que los "lenguajes pequeños" tienen un gran potencial
  • Pero todavía quedan muchas preguntas sin responder
    • ¿Cómo se comunicarían entre sí estos lenguajes?
    • ¿Deberían compilarse a una representación intermedia común?
    • ¿O deberían coexistir distintos runtimes en paralelo y comunicarse mediante protocolos estándar (¿como las tuberías Unix, TCP/IP?)?
    • ¿O cada lenguaje sería lo bastante pequeño como para poder reimplementarse sobre varios lenguajes anfitriones?
    • ¿O tal vez la dirección correcta sea combinar todo eso?
  • En cualquier caso, estoy convencido de que necesitamos imaginar una forma diferente de construir software
    • Tal vez los "lenguajes pequeños" puedan ser parte de esa historia
    • Lo importante es dejar de apilar más ladrillos sobre lo que ya existe durante el tiempo suficiente como para poder imaginar algo mejor

7 comentarios

 
ide127 2022-12-15

"
Creemos que crear un “lenguaje” adecuado para el problema que necesitamos resolver facilita más la resolución del problema y hace que la solución sea más fácil de entender y, al mismo tiempo, más pequeña.
"

Lo que sentí al leer esta parte es que, al final, eso de un “lenguaje pequeño” quizá no significa básicamente lo mismo que un framework. Como en el caso de JavaScript -> React, donde se obligan funciones y patrones de diseño de uso frecuente para convertirlos en una especie de gramática.

 
chicol 2022-12-14

Es un tema interesante.

 
kunggom 2022-12-12

Ahora que lo pienso, hace poco descubrí una herramienta de generación de DSL llamada MPS (Meta Programming System) creada por JetBrains.
Resulta que es algo bastante más antiguo de lo que pensaba. Me llamó la atención y he querido revisarla más a fondo, pero por una cosa u otra lo he ido posponiendo; si alguien la ha usado, me gustaría escuchar alguna reseña o experiencia de uso.

 
uglyduck68 2022-12-12

Guau, gracias

 
nicewook 2022-12-12

Gracias por compartirlo.

 
roxie 2022-12-12

Lisp sonriendo de oreja a oreja

 
xguru 2022-12-12

Me pareció una historia interesante, así que la comparto.