Le Langage Centenaire
Avril 2003
(Cet essai est tiré d'une conférence donnée à PyCon 2003.)
Il est difficile de prédire à quoi ressemblera la vie dans cent ans. Il n'y a que quelques certitudes. Nous savons que tout le monde conduira des voitures volantes, que les lois de zonage seront assouplies pour permettre des bâtiments de centaines d'étages, qu'il fera sombre la plupart du temps, et que toutes les femmes seront entraînées aux arts martiaux. Ici, je veux me concentrer sur un détail de cette image. Quel type de langage de programmation utiliseront-ils pour écrire le logiciel contrôlant ces voitures volantes ?
Cela vaut la peine d'y réfléchir, non pas tant parce que nous utiliserons réellement ces langages, mais parce que, si nous avons de la chance, nous utiliserons des langages sur le chemin de ce point à celui-là.
Je pense que, comme les espèces, les langages formeront des arbres évolutifs, avec des impasses se ramifiant partout. Nous pouvons déjà le constater. Cobol, malgré sa popularité passée, ne semble pas avoir de descendants intellectuels. C'est une impasse évolutive – un langage de Néandertal.
Je prédis un sort similaire pour Java. Les gens m'envoient parfois des courriels disant : « Comment pouvez-vous dire que Java ne sera pas un langage réussi ? C'est déjà un langage réussi. » Et j'admets que c'est le cas, si l'on mesure le succès par l'espace occupé par les livres qui lui sont consacrés (en particulier les livres individuels), ou par le nombre d'étudiants de premier cycle qui croient devoir l'apprendre pour trouver un emploi. Quand je dis que Java ne sera pas un langage réussi, je veux dire quelque chose de plus précis : que Java s'avérera être une impasse évolutive, comme Cobol.
Ce n'est qu'une supposition. Je peux me tromper. Mon but ici n'est pas de dénigrer Java, mais de soulever la question des arbres évolutifs et d'amener les gens à se demander : où se situe le langage X sur l'arbre ? La raison de poser cette question n'est pas seulement pour que nos fantômes puissent dire, dans cent ans, « Je vous l'avais dit ». C'est parce que rester proche des branches principales est une heuristique utile pour trouver des langages qui seront bons à programmer dès maintenant.
À tout moment, vous êtes probablement plus heureux sur les branches principales d'un arbre évolutif. Même quand il y avait encore beaucoup de Néandertaliens, ça devait être pénible d'en être un. Les Cro-Magnons seraient constamment venus vous battre et vous voler votre nourriture.
La raison pour laquelle je veux savoir à quoi ressembleront les langages dans cent ans est de savoir sur quelle branche de l'arbre parier maintenant.
L'évolution des langages diffère de l'évolution des espèces car les branches peuvent converger. La branche Fortran, par exemple, semble fusionner avec les descendants d'Algol. En théorie, c'est aussi possible pour les espèces, mais il est peu probable que cela se soit produit pour des organismes plus grands qu'une cellule.
La convergence est plus probable pour les langages en partie parce que l'espace des possibles est plus petit, et en partie parce que les mutations ne sont pas aléatoires. Les concepteurs de langages incorporent délibérément des idées d'autres langages.
Il est particulièrement utile pour les concepteurs de langages de réfléchir à la direction que prendra probablement l'évolution des langages de programmation, car ils peuvent ainsi orienter leurs choix. Dans ce cas, « rester sur une branche principale » devient plus qu'un moyen de choisir un bon langage. Cela devient une heuristique pour prendre les bonnes décisions en matière de conception de langage.
Tout langage de programmation peut être divisé en deux parties : un ensemble d'opérateurs fondamentaux qui jouent le rôle d'axiomes, et le reste du langage, qui pourrait en principe être écrit en termes de ces opérateurs fondamentaux.
Je pense que les opérateurs fondamentaux sont le facteur le plus important pour la survie à long terme d'un langage. Le reste, vous pouvez le changer. C'est comme la règle qui dit que pour acheter une maison, il faut d'abord considérer l'emplacement. Tout le reste peut être réparé plus tard, mais vous ne pouvez pas réparer l'emplacement.
Je pense qu'il est important non seulement que les axiomes soient bien choisis, mais qu'ils soient peu nombreux. Les mathématiciens ont toujours pensé ainsi des axiomes – moins il y en a, mieux c'est – et je pense qu'ils tiennent quelque chose.
À tout le moins, c'est un exercice utile d'examiner attentivement le cœur d'un langage pour voir s'il y a des axiomes qui pourraient être éliminés. J'ai constaté, au cours de ma longue carrière de désordonné, que le désordre engendre le désordre, et j'ai vu cela se produire dans les logiciels ainsi que sous les lits et dans les coins des pièces.
J'ai l'intuition que les branches principales de l'arbre évolutif passent par les langages qui ont les noyaux les plus petits et les plus propres. Plus un langage peut s'écrire lui-même, mieux c'est.
Bien sûr, je fais une grande supposition en me demandant même à quoi ressembleront les langages de programmation dans cent ans. Écrirons-nous même des programmes dans cent ans ? Ne dirons-nous pas simplement aux ordinateurs ce que nous voulons qu'ils fassent ?
Il n'y a pas eu beaucoup de progrès dans ce domaine jusqu'à présent. Je suppose que dans cent ans, les gens diront toujours aux ordinateurs quoi faire en utilisant des programmes que nous reconnaîtrions comme tels. Il y aura peut-être des tâches que nous résolvons maintenant en écrivant des programmes et pour lesquelles, dans cent ans, il ne sera plus nécessaire d'écrire des programmes, mais je pense qu'il y aura encore une bonne part de programmation du type que nous faisons aujourd'hui.
Il peut sembler présomptueux de penser que quiconque peut prédire à quoi ressemblera une technologie dans cent ans. Mais rappelez-vous que nous avons déjà près de cinquante ans d'histoire derrière nous. Regarder cent ans en avant est une idée saisissable si l'on considère la lenteur avec laquelle les langages ont évolué au cours des cinquante dernières années.
Les langages évoluent lentement parce qu'ils ne sont pas vraiment des technologies. Les langages sont une notation. Un programme est une description formelle du problème que vous voulez qu'un ordinateur résolve pour vous. Ainsi, le taux d'évolution des langages de programmation est plus proche du taux d'évolution de la notation mathématique que, par exemple, des transports ou des communications. La notation mathématique évolue, mais pas avec les bonds de géant que l'on observe dans la technologie.
De quoi que soient faits les ordinateurs dans cent ans, il semble sûr de prédire qu'ils seront beaucoup plus rapides qu'aujourd'hui. Si la loi de Moore continue de s'appliquer, ils seront 74 quintillions (73 786 976 294 838 206 464) de fois plus rapides. C'est assez difficile à imaginer. Et en effet, la prédiction la plus probable en matière de vitesse pourrait être que la loi de Moore cessera de fonctionner. Tout ce qui est censé doubler tous les dix-huit mois semble susceptible de se heurter à une sorte de limite fondamentale à terme. Mais je n'ai aucun mal à croire que les ordinateurs seront beaucoup plus rapides. Même s'ils ne sont qu'un million de fois plus rapides, cela devrait changer substantiellement les règles du jeu pour les langages de programmation. Entre autres choses, il y aura plus de place pour ce qui serait maintenant considéré comme des langages lents, c'est-à-dire des langages qui ne produisent pas de code très efficace.
Et pourtant, certaines applications exigeront toujours de la vitesse. Certains des problèmes que nous voulons résoudre avec les ordinateurs sont créés par les ordinateurs ; par exemple, le taux auquel vous devez traiter des images vidéo dépend du taux auquel un autre ordinateur peut les générer. Et il existe une autre catégorie de problèmes qui ont intrinsèquement une capacité illimitée à absorber des cycles : le rendu d'images, la cryptographie, les simulations.
Si certaines applications peuvent être de plus en plus inefficaces tandis que d'autres continuent d'exiger toute la vitesse que le matériel peut offrir, des ordinateurs plus rapides signifieront que les langages devront couvrir une gamme d'efficacités toujours plus large. Nous avons déjà vu cela se produire. Les implémentations actuelles de certains nouveaux langages populaires sont étonnamment gaspilleuses par rapport aux standards des décennies précédentes.
Ce n'est pas seulement quelque chose qui se produit avec les langages de programmation. C'est une tendance historique générale. À mesure que les technologies s'améliorent, chaque génération peut faire des choses que la génération précédente aurait considérées comme du gaspillage. Les gens d'il y a trente ans seraient étonnés de la désinvolture avec laquelle nous passons des appels téléphoniques longue distance. Les gens d'il y a cent ans seraient encore plus étonnés qu'un colis puisse un jour voyager de Boston à New York via Memphis.
Je peux déjà vous dire ce qui va arriver à tous ces cycles supplémentaires que le matériel plus rapide nous donnera dans les cent prochaines années. Ils seront presque tous gaspillés.
J'ai appris à programmer quand la puissance informatique était rare. Je me souviens avoir retiré tous les espaces de mes programmes Basic pour qu'ils tiennent dans la mémoire d'un TRS-80 de 4 Ko. L'idée de tout ce logiciel incroyablement inefficace qui brûle des cycles en faisant la même chose encore et encore me semble un peu grossière. Mais je pense que mes intuitions sont fausses ici. Je suis comme quelqu'un qui a grandi pauvre et ne peut se résoudre à dépenser de l'argent même pour quelque chose d'important, comme aller chez le médecin.
Certains types de gaspillage sont vraiment dégoûtants. Les SUV, par exemple, seraient sans doute grossiers même s'ils fonctionnaient avec un carburant inépuisable et ne généraient aucune pollution. Les SUV sont grossiers parce qu'ils sont la solution à un problème grossier. (Comment rendre les monospaces plus masculins.) Mais tout gaspillage n'est pas mauvais. Maintenant que nous avons l'infrastructure pour le supporter, compter les minutes de vos appels longue distance commence à sembler mesquin. Si vous avez les ressources, il est plus élégant de considérer tous les appels téléphoniques comme une seule et même chose, peu importe où se trouve l'autre personne.
Il y a le bon gaspillage, et le mauvais gaspillage. Je m'intéresse au bon gaspillage – celui où, en dépensant plus, nous pouvons obtenir des conceptions plus simples. Comment allons-nous profiter des opportunités de gaspiller des cycles que nous obtiendrons grâce au nouveau matériel plus rapide ?
Le désir de vitesse est si profondément ancré en nous, avec nos ordinateurs chétifs, qu'il faudra un effort conscient pour le surmonter. Dans la conception des langages, nous devrions rechercher consciemment les situations où nous pouvons échanger l'efficacité contre la moindre augmentation de commodité.
La plupart des structures de données existent à cause de la vitesse. Par exemple, de nombreux langages aujourd'hui ont à la fois des chaînes de caractères (strings) et des listes. Sémantiquement, les chaînes de caractères sont plus ou moins un sous-ensemble des listes dont les éléments sont des caractères. Alors pourquoi avez-vous besoin d'un type de données séparé ? Vous n'en avez pas vraiment besoin. Les chaînes de caractères n'existent que pour l'efficacité. Mais c'est boiteux d'encombrer la sémantique du langage avec des astuces pour faire fonctionner les programmes plus vite. Avoir des chaînes de caractères dans un langage semble être un cas d'optimisation prématurée.
Si nous considérons le cœur d'un langage comme un ensemble d'axiomes, il est sûrement grossier d'avoir des axiomes supplémentaires qui n'ajoutent aucune puissance expressive, simplement par souci d'efficacité. L'efficacité est importante, mais je ne pense pas que ce soit la bonne façon de l'obtenir.
La bonne façon de résoudre ce problème, je pense, est de séparer la signification d'un programme des détails d'implémentation. Au lieu d'avoir à la fois des listes et des chaînes de caractères, n'ayez que des listes, avec un moyen de donner au compilateur des conseils d'optimisation qui lui permettront d'organiser les chaînes de caractères en octets contigus si nécessaire.
Comme la vitesse n'a pas d'importance dans la plupart des programmes, vous n'aurez normalement pas besoin de vous soucier de ce genre de microgestion. Cela sera de plus en plus vrai à mesure que les ordinateurs deviendront plus rapides.
En dire moins sur l'implémentation devrait également rendre les programmes plus flexibles. Les spécifications changent pendant qu'un programme est écrit, et ce n'est pas seulement inévitable, mais souhaitable.
Le mot « essai » vient du verbe français « essayer », qui signifie « tenter ». Un essai, au sens original, est quelque chose que l'on écrit pour essayer de comprendre quelque chose. Cela se produit aussi dans les logiciels. Je pense que certains des meilleurs programmes étaient des essais, dans le sens où les auteurs ne savaient pas exactement ce qu'ils essayaient d'écrire quand ils ont commencé.
Les hackers Lisp connaissent déjà la valeur de la flexibilité avec les structures de données. Nous avons tendance à écrire la première version d'un programme de manière à ce qu'il fasse tout avec des listes. Ces versions initiales peuvent être si étonnamment inefficaces qu'il faut un effort conscient pour ne pas penser à ce qu'elles font, tout comme, pour moi du moins, manger un steak exige un effort conscient pour ne pas penser d'où il vient.
Ce que les programmeurs dans cent ans rechercheront, par-dessus tout, c'est un langage où l'on peut assembler une version 1 incroyablement inefficace d'un programme avec le moins d'effort possible. Du moins, c'est ainsi que nous le décririons en termes actuels. Ce qu'ils diront, c'est qu'ils veulent un langage facile à programmer.
Un logiciel inefficace n'est pas grossier. Ce qui est grossier, c'est un langage qui oblige les programmeurs à faire un travail inutile. Gaspiller le temps du programmeur est la véritable inefficacité, pas gaspiller le temps machine. Cela deviendra de plus en plus clair à mesure que les ordinateurs deviendront plus rapides.
Je pense que se débarrasser des chaînes de caractères est déjà quelque chose que nous pourrions envisager. Nous l'avons fait dans Arc, et cela semble être un avantage ; certaines opérations qui seraient difficiles à décrire comme des expressions régulières peuvent être décrites facilement comme des fonctions récursives.
Jusqu'où ira cet aplatissement des structures de données ? Je peux imaginer des possibilités qui me choquent même moi, avec mon esprit consciencieusement élargi. Nous débarrasserons-nous des tableaux, par exemple ? Après tout, ce ne sont qu'un sous-ensemble des tables de hachage où les clés sont des vecteurs d'entiers. Remplacerons-nous les tables de hachage elles-mêmes par des listes ?
Il y a des perspectives encore plus choquantes. Le Lisp que McCarthy a décrit en 1960, par exemple, n'avait pas de nombres. Logiquement, vous n'avez pas besoin d'avoir une notion séparée de nombres, car vous pouvez les représenter comme des listes : l'entier n pourrait être représenté comme une liste de n éléments. Vous pouvez faire des calculs de cette manière. C'est juste d'une inefficacité insupportable.
Personne n'a réellement proposé d'implémenter les nombres comme des listes en pratique. En fait, l'article de McCarthy de 1960 n'était pas, à l'époque, destiné à être implémenté du tout. C'était un exercice théorique, une tentative de créer une alternative plus élégante à la Machine de Turing. Quand quelqu'un a, de manière inattendue, pris cet article et l'a traduit en un interpréteur Lisp fonctionnel, les nombres n'étaient certainement pas représentés comme des listes ; ils étaient représentés en binaire, comme dans tout autre langage.
Un langage de programmation pourrait-il aller jusqu'à se débarrasser des nombres en tant que type de données fondamental ? Je pose cette question non pas tant comme une question sérieuse que comme un moyen de jouer à la poule mouillée avec l'avenir. C'est comme le cas hypothétique d'une force irrésistible rencontrant un objet inamovible – ici, une implémentation inimaginablement inefficace rencontrant des ressources inimaginablement grandes. Je ne vois pas pourquoi pas. L'avenir est assez long. S'il y a quelque chose que nous pouvons faire pour diminuer le nombre d'axiomes dans le langage de base, cela semblerait être le côté sur lequel parier lorsque t tend vers l'infini. Si l'idée semble encore insupportable dans cent ans, peut-être ne le sera-t-elle pas dans mille.
Juste pour être clair à ce sujet, je ne propose pas que tous les calculs numériques soient réellement effectués à l'aide de listes. Je propose que le langage de base, avant toute notation supplémentaire concernant l'implémentation, soit défini de cette manière. En pratique, tout programme qui voudrait faire des calculs mathématiques représenterait probablement les nombres en binaire, mais ce serait une optimisation, et non une partie de la sémantique du langage de base.
Une autre façon de consommer des cycles est d'avoir de nombreuses couches logicielles entre l'application et le matériel. C'est aussi une tendance que nous observons déjà : de nombreux langages récents sont compilés en bytecode. Bill Woods m'a dit un jour qu'en règle générale, chaque couche d'interprétation coûte un facteur 10 en vitesse. Ce coût supplémentaire vous offre de la flexibilité.
La toute première version d'Arc était un cas extrême de ce type de lenteur multi-niveaux, avec des avantages correspondants. C'était un interpréteur « métacirculaire » classique écrit au-dessus de Common Lisp, avec une ressemblance familiale certaine avec la fonction eval
définie dans l'article original de McCarthy sur Lisp. L'ensemble ne faisait que quelques centaines de lignes de code, il était donc très facile à comprendre et à modifier. Le Common Lisp que nous utilisions, CLisp, fonctionne lui-même au-dessus d'un interpréteur de bytecode. Nous avions donc ici deux niveaux d'interprétation, l'un d'eux (le supérieur) étant étonnamment inefficace, et le langage était utilisable. À peine utilisable, je l'admets, mais utilisable.
Écrire des logiciels en plusieurs couches est une technique puissante, même au sein des applications. La programmation ascendante (bottom-up) consiste à écrire un programme comme une série de couches, chacune servant de langage pour celle du dessus. Cette approche tend à produire des programmes plus petits et plus flexibles. C'est aussi la meilleure voie vers ce Graal, la réutilisabilité. Un langage est par définition réutilisable. Plus vous pouvez pousser votre application vers un langage pour écrire ce type d'application, plus votre logiciel sera réutilisable.
D'une manière ou d'une autre, l'idée de réutilisabilité s'est attachée à la programmation orientée objet dans les années 1980, et aucune quantité de preuves contraires ne semble pouvoir la déloger. Mais bien que certains logiciels orientés objet soient réutilisables, ce qui les rend réutilisables est leur approche ascendante (bottom-up), et non leur orientation objet. Considérez les bibliothèques : elles sont réutilisables parce qu'elles sont un langage, qu'elles soient écrites dans un style orienté objet ou non.
Je ne prédis pas la disparition de la programmation orientée objet, au fait. Bien que je ne pense pas qu'elle ait beaucoup à offrir aux bons programmeurs, sauf dans certains domaines spécialisés, elle est irrésistible pour les grandes organisations. La programmation orientée objet offre un moyen durable d'écrire du code spaghetti. Elle permet d'accumuler des programmes comme une série de correctifs. Les grandes organisations ont toujours tendance à développer des logiciels de cette manière, et je m'attends à ce que cela soit aussi vrai dans cent ans qu'aujourd'hui.
Tant que nous parlons de l'avenir, nous ferions mieux de parler de calcul parallèle, car c'est là que cette idée semble vivre. C'est-à-dire que, peu importe quand vous en parlez, le calcul parallèle semble être quelque chose qui va se produire dans le futur.
L'avenir le rattrapera-t-il un jour ? Les gens parlent de calcul parallèle comme de quelque chose d'imminent depuis au moins 20 ans, et cela n'a pas beaucoup affecté la pratique de la programmation jusqu'à présent. Ou bien si ? Déjà, les concepteurs de puces doivent y penser, tout comme les personnes qui tentent d'écrire des logiciels système sur des ordinateurs multi-CPU.
La vraie question est de savoir jusqu'où le parallélisme montera-t-il dans l'échelle de l'abstraction ? Dans cent ans, affectera-t-il même les programmeurs d'applications ? Ou sera-ce quelque chose auquel les rédacteurs de compilateurs penseront, mais qui sera généralement invisible dans le code source des applications ?
Une chose qui semble probable est que la plupart des opportunités de parallélisme seront gaspillées. C'est un cas particulier de ma prédiction plus générale selon laquelle la majeure partie de la puissance informatique supplémentaire qui nous sera donnée sera gaspillée. Je m'attends à ce que, comme pour la vitesse stupéfiante du matériel sous-jacent, le parallélisme soit quelque chose de disponible si vous le demandez explicitement, mais qui ne sera pas utilisé habituellement. Cela implique que le type de parallélisme que nous aurons dans cent ans ne sera pas, sauf dans des applications spéciales, un parallélisme massif. Je m'attends à ce que pour les programmeurs ordinaires, ce soit plus comme la possibilité de lancer des processus qui finissent tous par s'exécuter en parallèle.
Et cela, comme demander des implémentations spécifiques de structures de données, sera quelque chose que vous ferez assez tard dans la vie d'un programme, lorsque vous tenterez de l'optimiser. Les versions 1 ignoreront généralement tout avantage à tirer du calcul parallèle, tout comme elles ignoreront les avantages à tirer de représentations spécifiques des données.
Sauf dans des types d'applications spéciales, le parallélisme ne pervadera pas les programmes écrits dans cent ans. Ce serait une optimisation prématurée si c'était le cas.
Combien de langages de programmation y aura-t-il dans cent ans ? Il semble y avoir un grand nombre de nouveaux langages de programmation ces derniers temps. Une partie de la raison est que le matériel plus rapide a permis aux programmeurs de faire des compromis différents entre vitesse et commodité, selon l'application. Si c'est une vraie tendance, le matériel que nous aurons dans cent ans ne devrait que l'accentuer.
Et pourtant, il n'y aura peut-être que quelques langages largement utilisés dans cent ans. Une partie de la raison pour laquelle je dis cela est l'optimisme : il semble que, si vous faisiez un très bon travail, vous pourriez créer un langage idéal pour écrire une version 1 lente, et pourtant, avec les bons conseils d'optimisation au compilateur, il produirait également un code très rapide si nécessaire. Donc, comme je suis optimiste, je vais prédire que malgré l'énorme écart qu'ils auront entre l'efficacité acceptable et l'efficacité maximale, les programmeurs dans cent ans auront des langages capables de couvrir la majeure partie de cet écart.
À mesure que cet écart se creuse, les profileurs deviendront de plus en plus importants. On accorde peu d'attention au profilage actuellement. Beaucoup de gens semblent encore croire que la façon d'obtenir des applications rapides est d'écrire des compilateurs qui génèrent du code rapide. À mesure que l'écart entre la performance acceptable et la performance maximale s'élargit, il deviendra de plus en plus clair que la façon d'obtenir des applications rapides est d'avoir un bon guide de l'une à l'autre.
Quand je dis qu'il n'y aura peut-être que quelques langages, je n'inclus pas les « petits langages » spécifiques à un domaine. Je pense que de tels langages embarqués sont une excellente idée, et je m'attends à ce qu'ils prolifèrent. Mais je m'attends à ce qu'ils soient écrits comme des couches suffisamment minces pour que les utilisateurs puissent voir le langage à usage général en dessous.
Qui concevra les langages du futur ? L'une des tendances les plus excitantes des dix dernières années a été l'essor des langages open-source comme Perl, Python et Ruby. La conception des langages est prise en charge par les hackers. Les résultats jusqu'à présent sont désordonnés, mais encourageants. Il y a des idées étonnamment nouvelles dans Perl, par exemple. Beaucoup sont étonnamment mauvaises, mais c'est toujours le cas des efforts ambitieux. À son rythme de mutation actuel, Dieu sait en quoi Perl pourrait évoluer dans cent ans.
Il n'est pas vrai que ceux qui ne peuvent pas faire, enseignent (certains des meilleurs hackers que je connaisse sont professeurs), mais il est vrai qu'il y a beaucoup de choses que ceux qui enseignent ne peuvent pas faire. La recherche impose des restrictions de caste contraignantes. Dans tout domaine académique, il y a des sujets sur lesquels il est acceptable de travailler et d'autres qui ne le sont pas. Malheureusement, la distinction entre les sujets acceptables et interdits est généralement basée sur la façon dont le travail semble intellectuel lorsqu'il est décrit dans des articles de recherche, plutôt que sur son importance pour obtenir de bons résultats. Le cas extrême est probablement la littérature ; les personnes qui étudient la littérature disent rarement quoi que ce soit qui serait de la moindre utilité à ceux qui la produisent.
Bien que la situation soit meilleure dans les sciences, le chevauchement entre le type de travail que vous êtes autorisé à faire et le type de travail qui produit de bons langages est malheureusement faible. (Olin Shivers s'en est plaint avec éloquence.) Par exemple, les types semblent être une source inépuisable d'articles de recherche, malgré le fait que le typage statique semble exclure les vraies macros – sans lesquelles, à mon avis, aucun langage ne vaut la peine d'être utilisé.
La tendance n'est pas seulement vers des langages développés comme des projets open-source plutôt que comme de la « recherche », mais vers des langages conçus par les programmeurs d'applications qui ont besoin de les utiliser, plutôt que par les rédacteurs de compilateurs. Cela semble être une bonne tendance et je m'attends à ce qu'elle se poursuive.
Contrairement à la physique dans cent ans, qui est presque nécessairement impossible à prédire, je pense qu'il est peut-être possible en principe de concevoir dès maintenant un langage qui plairait aux utilisateurs dans cent ans.
Une façon de concevoir un langage est de simplement écrire le programme que vous aimeriez pouvoir écrire, qu'il existe ou non un compilateur capable de le traduire ou un matériel capable de l'exécuter. Lorsque vous faites cela, vous pouvez supposer des ressources illimitées. Il semble que nous devrions être capables d'imaginer des ressources illimitées aussi bien aujourd'hui que dans cent ans.
Quel programme aimerait-on écrire ? Celui qui demande le moins de travail. Sauf que ce n'est pas tout à fait ça : celui qui demanderait le moins de travail si vos idées sur la programmation n'étaient pas déjà influencées par les langages auxquels vous êtes actuellement habitué. Une telle influence peut être si omniprésente qu'il faut un grand effort pour la surmonter. On pourrait penser qu'il serait évident pour des créatures aussi paresseuses que nous de savoir comment exprimer un programme avec le moins d'effort. En fait, nos idées sur ce qui est possible ont tendance à être si limitées par le langage dans lequel nous pensons que des formulations plus faciles de programmes semblent très surprenantes. C'est quelque chose que vous devez découvrir, pas quelque chose dans lequel vous vous enfoncez naturellement.
Une astuce utile ici est d'utiliser la longueur du programme comme approximation de la quantité de travail nécessaire pour l'écrire. Pas la longueur en caractères, bien sûr, mais la longueur en éléments syntaxiques distincts – en gros, la taille de l'arbre d'analyse. Il n'est peut-être pas tout à fait vrai que le programme le plus court est le moins de travail à écrire, mais c'est suffisamment proche pour qu'il vaille mieux viser la cible solide de la brièveté que celle, floue et proche, du moindre travail. Alors l'algorithme de conception de langage devient : regarder un programme et demander, y a-t-il un moyen de l'écrire plus court ?
En pratique, écrire des programmes dans un langage imaginaire de cent ans fonctionnera à des degrés divers selon votre proximité avec le cœur. Les routines de tri, vous pouvez les écrire maintenant. Mais il serait difficile de prédire maintenant quels types de bibliothèques pourraient être nécessaires dans cent ans. Vraisemblablement, de nombreuses bibliothèques seront destinées à des domaines qui n'existent même pas encore. Si SETI@home fonctionne, par exemple, nous aurons besoin de bibliothèques pour communiquer avec des extraterrestres. À moins bien sûr qu'ils ne soient suffisamment avancés pour communiquer déjà en XML.
À l'autre extrême, je pense que vous pourriez concevoir le langage de base aujourd'hui. En fait, certains pourraient soutenir qu'il était déjà en grande partie conçu en 1958.
Si le langage centenaire était disponible aujourd'hui, voudrions-nous programmer avec ? Une façon de répondre à cette question est de regarder en arrière. Si les langages de programmation actuels avaient été disponibles en 1960, quelqu'un aurait-il voulu les utiliser ?
À certains égards, la réponse est non. Les langages d'aujourd'hui supposent une infrastructure qui n'existait pas en 1960. Par exemple, un langage où l'indentation est significative, comme Python, ne fonctionnerait pas très bien sur les terminaux d'imprimante. Mais en mettant de côté de tels problèmes – en supposant, par exemple, que les programmes étaient tous simplement écrits sur papier – les programmeurs des années 1960 auraient-ils aimé écrire des programmes dans les langages que nous utilisons maintenant ?
Je pense que oui. Certains des moins imaginatifs, qui avaient des artefacts des premiers langages intégrés dans leurs idées de ce qu'était un programme, auraient pu avoir des difficultés. (Comment manipuler des données sans faire d'arithmétique de pointeur ? Comment implémenter des organigrammes sans goto
?) Mais je pense que les programmeurs les plus intelligents n'auraient eu aucun mal à tirer le meilleur parti des langages actuels, s'ils les avaient eus.
Si nous avions le langage centenaire maintenant, il ferait au moins un excellent pseudo-code. Qu'en est-il de l'utiliser pour écrire des logiciels ? Puisque le langage centenaire devra générer du code rapide pour certaines applications, il pourrait vraisemblablement générer du code suffisamment efficace pour fonctionner de manière acceptable sur notre matériel. Nous devrions peut-être donner plus de conseils d'optimisation que les utilisateurs dans cent ans, mais cela pourrait quand même être un gain net.
Maintenant, nous avons deux idées qui, si vous les combinez, suggèrent des possibilités intéressantes : (1) le langage centenaire pourrait, en principe, être conçu aujourd'hui, et (2) un tel langage, s'il existait, pourrait être bon à programmer dès aujourd'hui. Quand vous voyez ces idées exposées ainsi, il est difficile de ne pas penser : pourquoi ne pas essayer d'écrire le langage centenaire maintenant ?
Lorsque vous travaillez sur la conception d'un langage, je pense qu'il est bon d'avoir un tel objectif et de le garder consciemment à l'esprit. Lorsque vous apprenez à conduire, l'un des principes qu'on vous enseigne est d'aligner la voiture non pas en alignant le capot avec les lignes peintes sur la route, mais en visant un point au loin. Même si tout ce qui vous intéresse est ce qui se passe dans les trois prochains mètres, c'est la bonne réponse. Je pense que nous pouvons et devrions faire la même chose avec les langages de programmation.
Notes
Je crois que Lisp Machine Lisp a été le premier langage à incarner le principe selon lequel les déclarations (sauf celles des variables dynamiques) n'étaient que des conseils d'optimisation et ne changeraient pas la signification d'un programme correct. Common Lisp semble avoir été le premier à l'énoncer explicitement.
Remerciements à Trevor Blackwell, Robert Morris et Dan Giffin pour la lecture des ébauches de cet essai, et à Guido van Rossum, Jeremy Hylton, et le reste de l'équipe Python pour m'avoir invité à prendre la parole à PyCon.