Qu’est-ce qu’un "little language" ?
- Les « petits langages » sont des langages conçus dans le but de résoudre un problème précis
→ SQL, RegEx, Dhall,..
→ On les appelle aussi des DSL
Pourquoi a-t-on besoin de petits langages ?
- À mesure que les applications sont devenues beaucoup plus complexes, le code source a grossi lui aussi, tout en devenant plus difficile à comprendre
- L’onboarding des nouveaux arrivants est difficile, des erreurs surviennent faute de bien comprendre les dépendances, et les modifications de code deviennent de plus en plus compliquées à gérer
- Au cours des 10 dernières années, les bases de code ont été multipliées par 100 à 500
- Le noyau Linux a démarré en 1992 avec 10 000 lignes, puis 20 ans plus tard il atteignait 30 millions de lignes
- Ce n’est pas seulement parce que « les fonctionnalités ont augmenté ». C’est aussi parce que notre manière de fabriquer le logiciel a changé
- Le logiciel ressemble à la construction d’une pyramide : pour poser la dernière pierre, il faut beaucoup plus de pierres en dessous
Dépasser cette tendance
- Faut-il vraiment des centaines de milliers, voire des millions de lignes de code pour créer un OS moderne ?
- Alan Kay a remis en cause cette hypothèse en 2006 avec le programme STEPS
-
Nous pensons que créer un « langage » adapté au problème à résoudre rend la résolution plus facile, tout en produisant des solutions plus petites et plus faciles à comprendre
- Dans STEPS, ils ont créé un langage appelé Nile, qui a permis de reproduire des fonctionnalités proches d’un renderer Cairo de 44 000 lignes avec environ 300 lignes de code
Pourquoi les langages de haut niveau ne suffisent-ils pas ?
- Pourquoi ne pas simplement créer un langage généraliste d’un niveau encore plus élevé ?
- Personnellement, je pense que nous avons atteint un point de rendements décroissants (
diminishing returns) dans l’expressivité des langages généralistes - À quoi ressemblerait un langage encore plus haut niveau ? Si l’on prend Python comme exemple, il est déjà tellement haut niveau qu’il ressemble presque à du pseudo-code
- Le problème des langages généralistes, c’est qu’il faut d’abord traduire votre problème en algorithme, puis exprimer cet algorithme dans le langage cible
- Dans Programming Pearls de Jon Bentley en 1986, Donald Knuth et Doug McIlroy avaient été invités à écrire un programme comptant la fréquence des mots. Don l’a rédigé sur 10 pages en WEB, une variante de Pascal, avec des structures de données complexes
- Doug, lui, l’a implémenté avec une pipeline Unix de 6 lignes utilisant
tr,sort,uniq,sort,sed, etc.
Less is More
- Les commandes Unix ci-dessus montrent une autre caractéristique des petits langages.
« Des langages moins puissants et un runtime plus puissant » - Gonzalez parle de cette tendance dans "The end of history for programming"
- On déplace les problèmes du domaine utilisateur vers le runtime
- Le programme devient proche d’une expression mathématique pure, tandis que la complexité du runtime augmente fortement
- On déplace les problèmes du domaine utilisateur vers le runtime
- Les expressions régulières et SQL ne peuvent rien exprimer en dehors, respectivement, de la recherche textuelle et des opérations sur base de données
- C’est l’opposé d’un langage comme C, qui n’a pas de runtime et dans lequel tout peut être exprimé
- Les petits langages se situent à l’extrémité opposée du spectre de puissance de C
- Non seulement l’architecture de l’ordinateur y est abstraite, mais le type de programmes qu’on peut exprimer y est aussi limité ; ils sont donc, par conception, Turing-incomplete
- Cela peut sembler très restrictif, mais cela ouvre une nouvelle dimension de possibilités pour l’optimisation et l’analyse statique
Analyse statique
- Les langages moins puissants sont plus faciles à raisonner et peuvent offrir des garanties plus fortes que les langages généralistes
- Par exemple, Dhall est un "Total Functional Programming Language" destiné à générer des fichiers de configuration
- Autrement dit, pour éliminer le risque de boucle infinie, les programmes Dhall « garantissent » qu’ils « (1) ne plantent pas, et (2) se terminent dans un temps borné »
- Le point (1) est obtenu en n’autorisant pas les exceptions. Les opérations susceptibles d’échouer renvoient un résultat
Optional(une valeur peut être présente ou absente) - Le point (2) est obtenu en n’autorisant pas les définitions récursives
- Dans d’autres langages fonctionnels, la récursion est la méthode de base pour implémenter des boucles, mais Dhall doit s’appuyer sur la fonction
foldintégrée - L’absence de structure de boucle générale signifie que Dhall n’est pas Turing-complete. Mais comme ce n’est pas un langage à usage général, ce n’est pas un problème
- Plus un langage est petit, plus le raisonnement devient simple
- Par exemple, il est difficile de vérifier qu’un programme Python n’a pas d’autres effets de bord, alors qu’en SQL il suffit de voir si la requête commence par
SELECT
- Par exemple, il est difficile de vérifier qu’un programme Python n’a pas d’autres effets de bord, alors qu’en SQL il suffit de voir si la requête commence par
- Dans le cas de Nile, l’équipe STEPS avait besoin d’un débogueur graphique et l’a donc construit ; on peut le voir directement
- C’est possible précisément parce que Nile est un petit langage facile à analyser
Le besoin de vitesse
- Les langages de programmation plus puissants n’augmentent pas seulement le risque de bugs, ils peuvent aussi nuire aux performances
- Par exemple, si un programme n’est pas exprimé sous forme d’algorithme, le runtime peut choisir lui-même l’algorithme
- Des expressions lentes peuvent être remplacées par des versions plus rapides (à condition de pouvoir prouver qu’elles produisent le même résultat)
- Par exemple, une requête SQL n’indique pas comment elle doit être exécutée
- Le moteur de base de données peut librement décider quel plan d’exécution est le plus adapté
- utiliser un index, un index composite, ou scanner la table entière, par exemple
- Les moteurs de base de données modernes collectent aussi des statistiques sur la distribution des valeurs dans chaque colonne, ce qui leur permet de choisir à la volée le plan de requête statistiquement optimal
- Si la requête était fournie sous forme d’algorithme, tout cela serait impossible
- Le moteur de base de données peut librement décider quel plan d’exécution est le plus adapté
- L’un des « ingrédients secrets » qui ont rendu le langage Nile très concis était
Jitblt, un compilateur Just-in-Time pour le rendu graphique- À travers leurs échanges, les équipes STEPS et Cairo ont découvert qu’une grande partie du code de Cairo servait à optimiser manuellement les opérations de composition de pixels
- En théorie, ce travail pouvait être délégué à un compilateur
- Dan Amelang, de l’équipe Cairo, s’est porté volontaire pour implémenter ce compilateur : c’est ainsi qu’est né
Jitblt - Cela signifie que le travail d’optimisation du pipeline graphique pouvait être séparé de la description mathématique pure de ce qu’il fallait rendre,
ce qui a permis à Nile de s’exécuter aussi vite que le code Cairo original optimisé à la main
Small languages, Big Potential
- Alors, qu’est devenu STEPS ? Ont-ils réussi à créer un OS fonctionnant avec juste assez de code pour tenir sur un T-shirt ?
- Le résultat final de STEPS fut KSWorld
- Un OS complet intégrant un éditeur de documents et un tableur
- 17 000 lignes de code
- C’est un peu trop long pour tenir sur un T-shirt, mais pour moi c’est quand même une réussite
- La création de KSWorld montre que les « petits langages » ont un grand potentiel
- Mais beaucoup de questions restent encore sans réponse
- Comment ces langages peuvent-ils dialoguer entre eux ?
- Faut-il les compiler vers une représentation intermédiaire commune ?
- Ou bien différents runtimes doivent-ils coexister en parallèle et communiquer via des protocoles standard (comme les pipelines Unix, TCP/IP, etc.) ?
- Ou bien chaque langage est-il assez petit pour pouvoir être réimplémenté dans plusieurs langages hôtes ?
- Peut-être que la bonne direction consiste à combiner toutes ces approches ?
- Quoi qu’il en soit, je suis convaincu que nous devons imaginer d’autres façons de construire le logiciel
- Peut-être que les « petits langages » feront partie de cette histoire
- L’important est de cesser d’empiler toujours plus de briques les unes sur les autres pendant assez longtemps pour pouvoir imaginer quelque chose de meilleur
7 commentaires
"
Nous pensons que créer un « langage » adapté au problème à résoudre facilite la résolution du problème, et permet de concevoir une solution plus facile à comprendre tout en restant plus petite.
"
En lisant ce passage, je me suis dit qu’au fond, ce qu’on appelle un « petit langage » n’a-t-il pas finalement le même sens qu’un framework ? Comme dans le cas de
JavaScript -> React, où l’on impose des fonctions fréquemment utilisées et des design patterns pour en faire une sorte de grammaire.Sujet intéressant.
À bien y réfléchir, j’ai récemment découvert un outil de génération de DSL appelé MPS (Meta Programming System), créé par JetBrains.
Il s’avère que c’est un outil bien plus ancien que je ne le pensais. Ça m’intéresse, donc j’envisageais de l’examiner d’un peu plus près, mais je remets ça sans cesse à plus tard ; si quelqu’un ici l’a déjà utilisé, j’aimerais beaucoup avoir un retour d’expérience.
Waouh, merci !
Merci pour cette lecture.
Le Lisp est tout sourire.
Je trouve que c’est une histoire intéressante, alors je la partage.