Cinq questions sur la conception des langages

Mai 2001

(Voici quelques notes que j'ai prises pour une table ronde sur la conception des langages de programmation au MIT le 10 mai 2001.)

1. Les langages de programmation sont pour les gens.

Les langages de programmation sont la manière dont les gens parlent aux ordinateurs. L'ordinateur serait tout aussi heureux de parler n'importe quel langage non ambigu. La raison pour laquelle nous avons des langages de haut niveau est que les gens ne peuvent pas gérer le langage machine. Le but des langages de programmation est d'empêcher nos pauvres et fragiles cerveaux humains d'être submergés par une masse de détails.

Les architectes savent que certains types de problèmes de conception sont plus personnels que d'autres. L'un des problèmes de conception les plus propres et les plus abstraits est la conception de ponts. Là, votre travail consiste principalement à franchir une distance donnée avec le moins de matériaux possible. L'autre extrémité du spectre est la conception de chaises. Les concepteurs de chaises doivent passer leur temps à penser aux fesses humaines.

Les logiciels varient de la même manière. Concevoir des algorithmes pour acheminer des données à travers un réseau est un problème agréable et abstrait, comme la conception de ponts. Tandis que concevoir des langages de programmation, c'est comme concevoir des chaises : il s'agit avant tout de gérer les faiblesses humaines.

La plupart d'entre nous détestent l'admettre. Concevoir des systèmes d'une grande élégance mathématique nous semble beaucoup plus attrayant que de céder aux faiblesses humaines. Et l'élégance mathématique a son rôle : certains types d'élégance rendent les programmes plus faciles à comprendre. Mais l'élégance n'est pas une fin en soi.

Et quand je dis que les langages doivent être conçus pour s'adapter aux faiblesses humaines, je ne veux pas dire que les langages doivent être conçus pour les mauvais programmeurs. En fait, je pense que vous devriez concevoir pour les meilleurs programmeurs, mais même les meilleurs programmeurs ont des limites. Je ne pense pas que quiconque aimerait programmer dans un langage où toutes les variables seraient la lettre x avec des indices entiers.

2. Concevez pour vous-même et vos amis.

Si vous regardez l'histoire des langages de programmation, beaucoup des meilleurs étaient des langages conçus pour être utilisés par leurs propres auteurs, et beaucoup des pires étaient conçus pour être utilisés par d'autres personnes.

Lorsque les langages sont conçus pour d'autres personnes, il s'agit toujours d'un groupe spécifique d'autres personnes : des personnes moins intelligentes que le concepteur du langage. Vous obtenez donc un langage qui vous prend de haut. Cobol est le cas le plus extrême, mais beaucoup de langages sont imprégnés de cet esprit.

Cela n'a rien à voir avec le degré d'abstraction du langage. C est assez bas niveau, mais il a été conçu pour être utilisé par ses auteurs, et c'est pourquoi les hackers l'apprécient.

L'argument en faveur de la conception de langages pour les mauvais programmeurs est qu'il y a plus de mauvais programmeurs que de bons programmeurs. C'est peut-être vrai. Mais ces quelques bons programmeurs écrivent un pourcentage disproportionnellement élevé des logiciels.

Je m'intéresse à la question : comment concevoir un langage que les meilleurs hackers apprécieront ? Il se trouve que je pense que c'est identique à la question : comment concevoir un bon langage de programmation ?, mais même si ce n'est pas le cas, c'est au moins une question intéressante.

3. Donnez au programmeur autant de contrôle que possible.

De nombreux langages (surtout ceux conçus pour d'autres personnes) ont l'attitude d'une gouvernante : ils essaient de vous empêcher de faire des choses qu'ils estiment ne pas être bonnes pour vous. J'aime l'approche inverse : donner au programmeur autant de contrôle que possible.

Lorsque j'ai appris Lisp pour la première fois, ce que j'ai le plus aimé, c'est qu'il me considérait comme un partenaire égal. Dans les autres langages que j'avais appris jusque-là, il y avait le langage et il y avait mon programme, écrit dans le langage, et les deux étaient très distincts. Mais en Lisp, les fonctions et les macros que j'écrivais étaient exactement comme celles qui composaient le langage lui-même. Je pouvais réécrire le langage si je le voulais. Cela avait le même attrait que les logiciels open-source.

4. Visez la brièveté.

La brièveté est sous-estimée et même méprisée. Mais si vous regardez au fond du cœur des hackers, vous verrez qu'ils l'adorent vraiment. Combien de fois avez-vous entendu des hackers parler avec affection de la façon dont, par exemple, en APL, ils pouvaient faire des choses étonnantes avec seulement quelques lignes de code ? Je pense que tout ce que les gens vraiment intelligents aiment vraiment mérite qu'on s'y intéresse.

Je pense que presque tout ce que vous pouvez faire pour raccourcir les programmes est bon. Il devrait y avoir beaucoup de fonctions de bibliothèque ; tout ce qui peut être implicite devrait l'être ; la syntaxe devrait être excessivement concise ; même les noms des choses devraient être courts.

Et il n'y a pas que les programmes qui devraient être courts. Le manuel devrait également être mince. Une bonne partie des manuels est occupée par des clarifications, des réserves, des avertissements et des cas particuliers. Si vous vous forcez à raccourcir le manuel, dans le meilleur des cas, vous le faites en corrigeant les éléments du langage qui nécessitaient tant d'explications.

5. Admettez ce qu'est le hacking.

Beaucoup de gens souhaitent que le hacking soit des mathématiques, ou du moins quelque chose comme une science naturelle. Je pense que le hacking ressemble plus à l'architecture. L'architecture est liée à la physique, dans le sens où les architectes doivent concevoir des bâtiments qui ne s'effondrent pas, mais le véritable objectif des architectes est de créer de grands bâtiments, et non de faire des découvertes sur la statique.

Ce que les hackers aiment faire, c'est créer de grands programmes. Et je pense, du moins dans nos propres esprits, que nous devons nous rappeler que c'est une chose admirable d'écrire de grands programmes, même lorsque ce travail ne se traduit pas facilement dans la monnaie intellectuelle conventionnelle des articles de recherche. Intellectuellement, il est tout aussi valable de concevoir un langage que les programmeurs aimeront que de concevoir un langage horrible qui incarne une idée sur laquelle vous pouvez publier un article.

1. Comment organiser de grandes bibliothèques ?

Les bibliothèques deviennent une composante de plus en plus importante des langages de programmation. Elles deviennent également plus grandes, ce qui peut être dangereux. S'il faut plus de temps pour trouver la fonction de bibliothèque qui fera ce que vous voulez qu'il n'en faudrait pour l'écrire vous-même, alors tout ce code ne fait rien d'autre que d'épaissir votre manuel. (Les manuels Symbolics en étaient un exemple.) Je pense donc que nous devrons travailler sur des moyens d'organiser les bibliothèques. L'idéal serait de les concevoir de manière à ce que le programmeur puisse deviner quel appel de bibliothèque ferait la bonne chose.

2. Les gens ont-ils vraiment peur de la syntaxe préfixée ?

C'est un problème ouvert dans le sens où je me le suis demandé pendant des années et je ne connais toujours pas la réponse. La syntaxe préfixée me semble parfaitement naturelle, sauf peut-être pour les mathématiques. Mais il se pourrait qu'une grande partie de l'impopularité de Lisp soit simplement due à une syntaxe peu familière. Savoir s'il faut faire quelque chose à ce sujet, si c'est vrai, est une autre question.

3. De quoi avez-vous besoin pour les logiciels basés sur serveur ?

Je pense que beaucoup des nouvelles applications les plus passionnantes qui seront écrites au cours des vingt prochaines années seront des applications Web, c'est-à-dire des programmes qui résident sur le serveur et vous parlent via un navigateur Web. Et pour écrire ce type de programmes, nous pourrions avoir besoin de nouvelles choses.

Une chose dont nous aurons besoin est le support pour la nouvelle façon dont les applications basées sur serveur sont publiées. Au lieu d'avoir une ou deux grandes versions par an, comme les logiciels de bureau, les applications basées sur serveur sont publiées sous forme de séries de petits changements. Vous pouvez avoir jusqu'à cinq ou dix versions par jour. Et en règle générale, tout le monde utilisera toujours la dernière version.

Vous savez comment concevoir des programmes pour qu'ils soient déboguables ? Eh bien, les logiciels basés sur serveur doivent également être conçus pour être modifiables. Vous devez pouvoir les modifier facilement, ou du moins savoir ce qui est un petit changement et ce qui est un changement capital.

Une autre chose qui pourrait s'avérer utile pour les logiciels basés sur serveur, étonnamment, ce sont les continuations. Dans les logiciels Web, vous pouvez utiliser quelque chose comme le style de passage de continuation pour obtenir l'effet de sous-programmes dans le monde intrinsèquement sans état d'une session Web. Peut-être vaudrait-il la peine d'avoir de véritables continuations, si ce n'était pas trop coûteux.

4. Quelles nouvelles abstractions reste-t-il à découvrir ?

Je ne suis pas sûr à quel point cet espoir est raisonnable, mais une chose que j'aimerais vraiment faire, personnellement, c'est découvrir une nouvelle abstraction – quelque chose qui ferait autant de différence que d'avoir des fonctions de première classe, la récursion ou même des paramètres nommés. C'est peut-être un rêve impossible. Ces choses ne sont pas découvertes si souvent. Mais je cherche toujours.

1. Vous pouvez utiliser le langage que vous voulez.

Écrire des programmes d'application signifiait autrefois écrire des logiciels de bureau. Et dans les logiciels de bureau, il y a un fort biais à écrire l'application dans le même langage que le système d'exploitation. Et il y a dix ans, écrire des logiciels signifiait à peu près écrire des logiciels en C. Finalement, une tradition a évolué : les programmes d'application ne doivent pas être écrits dans des langages inhabituels. Et cette tradition a eu tellement de temps pour se développer que des personnes non techniques comme les managers et les capital-risqueurs l'ont également apprise.

Les logiciels basés sur serveur font éclater tout ce modèle. Avec les logiciels basés sur serveur, vous pouvez utiliser n'importe quel langage que vous voulez. Presque personne ne le comprend encore (surtout pas les managers et les capital-risqueurs). Quelques hackers le comprennent, et c'est pourquoi nous entendons même parler de nouveaux langages indépendants comme Perl et Python. Nous n'entendons pas parler de Perl et Python parce que les gens les utilisent pour écrire des applications Windows.

Ce que cela signifie pour nous, en tant que personnes intéressées par la conception de langages de programmation, c'est qu'il existe désormais potentiellement un public réel pour notre travail.

2. La vitesse vient des profileurs.

Les concepteurs de langages, ou du moins les implémenteurs de langages, aiment écrire des compilateurs qui génèrent du code rapide. Mais je ne pense pas que ce soit ce qui rend les langages rapides pour les utilisateurs. Knuth a souligné il y a longtemps que la vitesse n'importe que dans quelques goulots d'étranglement critiques. Et quiconque a essayé sait qu'on ne peut pas deviner où se trouvent ces goulots d'étranglement. Les profileurs sont la réponse.

Les concepteurs de langages résolvent le mauvais problème. Les utilisateurs n'ont pas besoin que les benchmarks s'exécutent rapidement. Ce dont ils ont besoin, c'est d'un langage qui peut leur montrer quelles parties de leurs propres programmes doivent être réécrites. C'est de là que vient la vitesse en pratique. Alors peut-être que ce serait un gain net si les implémenteurs de langages prenaient la moitié du temps qu'ils auraient passé à faire des optimisations de compilateur et le passaient plutôt à écrire un bon profileur.

3. Vous avez besoin d'une application pour guider la conception d'un langage.

Ce n'est peut-être pas une règle absolue, mais il semble que les meilleurs langages aient tous évolué en même temps qu'une application pour laquelle ils étaient utilisés. C a été écrit par des personnes qui en avaient besoin pour la programmation système. Lisp a été développé en partie pour faire de la différenciation symbolique, et McCarthy était si impatient de commencer qu'il écrivait des programmes de différenciation même dans le premier article sur Lisp, en 1960.

C'est particulièrement bien si votre application résout un nouveau problème. Cela aura tendance à pousser votre langage à avoir de nouvelles fonctionnalités dont les programmeurs ont besoin. Personnellement, je suis intéressé par l'écriture d'un langage qui sera bon pour écrire des applications basées sur serveur.

[Pendant la table ronde, Guy Steele a également soulevé ce point, avec la suggestion supplémentaire que l'application ne devrait pas consister à écrire le compilateur de votre langage, à moins que votre langage ne soit destiné à écrire des compilateurs.]

4. Un langage doit être bon pour écrire des programmes jetables.

Vous savez ce qu'est un programme jetable : quelque chose que vous écrivez rapidement pour une tâche limitée. Je pense que si vous regardiez autour de vous, vous constateriez que beaucoup de grands programmes sérieux ont commencé comme des programmes jetables. Je ne serais pas surpris si la plupart des programmes commençaient comme des programmes jetables. Et donc, si vous voulez créer un langage qui soit bon pour écrire des logiciels en général, il doit être bon pour écrire des programmes jetables, car c'est le stade larvaire de la plupart des logiciels.

5. La syntaxe est liée à la sémantique.

Il est traditionnel de penser que la syntaxe et la sémantique sont complètement séparées. Cela peut sembler choquant, mais il se pourrait qu'elles ne le soient pas. Je pense que ce que vous voulez dans votre langage peut être lié à la façon dont vous l'exprimez.

Je parlais récemment à Robert Morris, et il a souligné que la surcharge d'opérateurs est un avantage plus important dans les langages à syntaxe infixée. Dans un langage à syntaxe préfixée, toute fonction que vous définissez est effectivement un opérateur. Si vous voulez définir un plus pour un nouveau type de nombre que vous avez créé, vous pouvez simplement définir une nouvelle fonction pour les additionner. Si vous faites cela dans un langage à syntaxe infixée, il y a une grande différence d'apparence entre l'utilisation d'un opérateur surchargé et un appel de fonction.

1. Nouveaux langages de programmation.

Dans les années 1970, il était à la mode de concevoir de nouveaux langages de programmation. Récemment, ce n'était plus le cas. Mais je pense que les logiciels basés sur serveur rendront les nouveaux langages à nouveau à la mode. Avec les logiciels basés sur serveur, vous pouvez utiliser n'importe quel langage que vous voulez, donc si quelqu'un conçoit un langage qui semble réellement meilleur que les autres disponibles, il y aura des gens qui prendront le risque de l'utiliser.

2. Le temps partagé.

Richard Kelsey a présenté cela comme une idée dont l'heure est revenue lors du dernier panel, et je suis entièrement d'accord avec lui. Ma supposition (et celle de Microsoft, semble-t-il) est qu'une grande partie de l'informatique passera du bureau aux serveurs distants. En d'autres termes, le temps partagé est de retour. Et je pense qu'il faudra le prendre en charge au niveau du langage. Par exemple, je sais que Richard et Jonathan Rees ont beaucoup travaillé sur l'implémentation de l'ordonnancement des processus au sein de Scheme 48.

3. Efficacité.

Récemment, il commençait à sembler que les ordinateurs étaient enfin assez rapides. De plus en plus, nous commencions à entendre parler de bytecode, ce qui implique pour moi au moins que nous avons des cycles à revendre. Mais je ne pense pas que ce sera le cas avec les logiciels basés sur serveur. Quelqu'un devra payer pour les serveurs sur lesquels le logiciel fonctionne, et le nombre d'utilisateurs qu'ils peuvent prendre en charge par machine sera le diviseur de leur coût en capital.

Je pense donc que l'efficacité comptera, du moins dans les goulots d'étranglement computationnels. Il sera particulièrement important de faire des E/S rapidement, car les applications basées sur serveur font beaucoup d'E/S.

Il se pourrait que le bytecode ne soit pas un avantage, au final. Sun et Microsoft semblent s'affronter dans une sorte de bataille des bytecodes en ce moment. Mais ils le font parce que le bytecode est un endroit pratique pour s'insérer dans le processus, et non parce que le bytecode est en soi une bonne idée. Il se pourrait que tout ce champ de bataille soit contourné. Ce serait assez amusant.

1. Clients.

Ce n'est qu'une supposition, mais ma supposition est que le modèle gagnant pour la plupart des applications sera purement basé sur le serveur. Concevoir un logiciel qui fonctionne en supposant que tout le monde aura votre client, c'est comme concevoir une société en supposant que tout le monde sera juste honnête. Ce serait certainement pratique, mais il faut supposer que cela n'arrivera jamais.

Je pense qu'il y aura une prolifération d'appareils ayant une sorte d'accès Web, et tout ce que vous pourrez supposer à leur sujet est qu'ils peuvent prendre en charge le HTML simple et les formulaires. Aurez-vous un navigateur sur votre téléphone portable ? Y aura-t-il un téléphone dans votre Palm Pilot ? Votre BlackBerry aura-t-il un écran plus grand ? Pourrez-vous naviguer sur le Web avec votre Game Boy ? Votre montre ? Je ne sais pas. Et je n'ai pas besoin de savoir si je parie sur le fait que tout est simplement sur le serveur. C'est tellement plus robuste d'avoir toutes les intelligences sur le serveur.

2. Programmation Orientée Objet.

Je réalise que c'est un sujet controversé, mais je ne pense pas que la programmation orientée objet soit si importante. Je pense que c'est un excellent modèle pour certains types d'applications qui nécessitent ce type spécifique de structure de données, comme les systèmes de fenêtres, les simulations et les programmes de CAO. Mais je ne vois pas pourquoi cela devrait être le modèle pour toute la programmation.

Je pense qu'une partie de la raison pour laquelle les gens dans les grandes entreprises aiment la programmation orientée objet est qu'elle génère beaucoup de ce qui ressemble à du travail. Quelque chose qui pourrait naturellement être représenté comme, disons, une liste d'entiers, peut maintenant être représenté comme une classe avec toutes sortes d'échafaudages et d'agitation.

Un autre attrait de la programmation orientée objet est que les méthodes vous donnent une partie de l'effet des fonctions de première classe. Mais ce n'est pas nouveau pour les programmeurs Lisp. Lorsque vous avez de véritables fonctions de première classe, vous pouvez simplement les utiliser de la manière appropriée à la tâche à accomplir, au lieu de tout forcer dans un moule de classes et de méthodes.

Ce que cela signifie pour la conception des langages, je pense, c'est qu'il ne faut pas intégrer la programmation orientée objet trop profondément. Peut-être la solution est-elle d'offrir des éléments sous-jacents plus généraux, et de laisser les gens concevoir les systèmes d'objets qu'ils veulent comme des bibliothèques.

3. Conception par comité.

Faire concevoir votre langage par un comité est un piège majeur, et pas seulement pour les raisons que tout le monde connaît. Tout le monde sait que les comités ont tendance à produire des conceptions inégales et incohérentes. Mais je pense qu'un danger plus grand est qu'ils ne prendront pas de risques. Lorsqu'une personne est aux commandes, elle peut prendre des risques sur lesquels un comité ne serait jamais d'accord.

Est-il nécessaire de prendre des risques pour concevoir un bon langage ? Beaucoup de gens pourraient soupçonner que la conception de langages est un domaine où il faut s'en tenir assez près à la sagesse conventionnelle. Je parie que ce n'est pas vrai. Dans tout ce que les gens font d'autre, la récompense est proportionnelle au risque. Pourquoi la conception de langages devrait-elle être différente ?