Loading...

ÊTRE POPULAIRE

Original

Mai 2001

(Cet article a été écrit comme une sorte de plan d'affaires pour un nouveau langage. Il manque donc (car il prend pour acquis) la caractéristique la plus importante d'un bon langage de programmation : des abstractions très puissantes.)

Un ami à moi a un jour dit à un éminent expert en systèmes d'exploitation qu'il voulait concevoir un langage de programmation vraiment bon. L'expert lui a dit que ce serait une perte de temps, que les langages de programmation ne deviennent pas populaires ou impopulaires en fonction de leurs mérites, et donc peu importe à quel point son langage était bon, personne ne l'utiliserait. Du moins, c'était ce qui était arrivé au langage qu'il avait conçu.

Qu'est-ce qui rend un langage populaire ? Les langages populaires méritent-ils leur popularité ? Vaut-il la peine d'essayer de définir un bon langage de programmation ? Comment le feriez-vous ?

Je pense que les réponses à ces questions peuvent être trouvées en observant les hackers et en apprenant ce qu'ils veulent. Les langages de programmation sont pour les hackers, et un langage de programmation est bon en tant que langage de programmation (plutôt que, disons, un exercice en sémantique dénotationnelle ou en conception de compilateurs) si et seulement si les hackers l'aiment.

1 La Mécanique de la Popularité

Il est vrai, certainement, que la plupart des gens ne choisissent pas les langages de programmation simplement en fonction de leurs mérites. La plupart des programmeurs se voient dire quel langage utiliser par quelqu'un d'autre. Et pourtant, je pense que l'effet de tels facteurs externes sur la popularité des langages de programmation n'est pas aussi grand qu'on le pense parfois. Je pense qu'un problème plus important est que l'idée d'un bon langage de programmation pour un hacker n'est pas la même que celle de la plupart des concepteurs de langages.

Entre les deux, l'opinion du hacker est celle qui compte. Les langages de programmation ne sont pas des théorèmes. Ce sont des outils, conçus pour les gens, et ils doivent être conçus pour s'adapter aux forces et aux faiblesses humaines autant que les chaussures doivent être conçues pour les pieds humains. Si une chaussure pince quand vous la mettez, c'est une mauvaise chaussure, peu importe à quel point elle peut être élégante en tant que pièce de sculpture.

Il se peut que la majorité des programmeurs ne puissent pas faire la différence entre un bon langage et un mauvais. Mais c'est la même chose avec tout autre outil. Cela ne signifie pas qu'il est inutile d'essayer de concevoir un bon langage. Les hackers experts peuvent reconnaître un bon langage quand ils en voient un, et ils l'utiliseront. Les hackers experts sont une toute petite minorité, il est vrai, mais cette petite minorité écrit tout le bon logiciel, et leur influence est telle que le reste des programmeurs aura tendance à utiliser quel que soit le langage qu'ils utilisent. Souvent, en effet, ce n'est pas seulement de l'influence mais un commandement : souvent, les hackers experts sont les mêmes personnes qui, en tant que leurs patrons ou conseillers académiques, disent aux autres programmeurs quel langage utiliser.

L'opinion des hackers experts n'est pas la seule force qui détermine la popularité relative des langages de programmation — les logiciels hérités (Cobol) et le battage médiatique (Ada, Java) jouent également un rôle — mais je pense que c'est la force la plus puissante à long terme. Étant donné une masse critique initiale et suffisamment de temps, un langage de programmation devient probablement aussi populaire qu'il le mérite. Et la popularité sépare encore plus les bons langages des mauvais, car les retours d'utilisateurs réels conduisent toujours à des améliorations. Regardez combien n'importe quel langage populaire a changé au cours de sa vie. Perl et Fortran sont des cas extrêmes, mais même Lisp a beaucoup changé. Lisp 1.5 n'avait pas de macros, par exemple ; celles-ci ont évolué plus tard, après que des hackers au MIT aient passé quelques années à utiliser Lisp pour écrire de vrais programmes. [1]

Donc, que ce soit ou non un langage doit être bon pour être populaire, je pense qu'un langage doit être populaire pour être bon. Et il doit rester populaire pour rester bon. L'état de l'art en langages de programmation ne reste pas figé. Et pourtant, les Lisps que nous avons aujourd'hui sont encore à peu près ce qu'ils avaient au MIT au milieu des années 1980, car c'est la dernière fois que Lisp avait une base d'utilisateurs suffisamment large et exigeante.

Bien sûr, les hackers doivent connaître un langage avant de pouvoir l'utiliser. Comment vont-ils en entendre parler ? D'autres hackers. Mais il doit y avoir un groupe initial de hackers utilisant le langage pour que d'autres en entendent parler. Je me demande combien ce groupe doit être ; combien d'utilisateurs constituent une masse critique ? De mémoire, je dirais vingt. Si un langage avait vingt utilisateurs distincts, c'est-à-dire vingt utilisateurs qui ont décidé par eux-mêmes de l'utiliser, je le considérerais comme réel.

Atteindre cela ne peut pas être facile. Je ne serais pas surpris si c'était plus difficile de passer de zéro à vingt que de vingt à mille. Le meilleur moyen d'obtenir ces vingt utilisateurs initiaux est probablement d'utiliser un cheval de Troie : donner aux gens une application qu'ils veulent, qui se trouve être écrite dans le nouveau langage.

2 Facteurs Externes

Commençons par reconnaître un facteur externe qui affecte la popularité d'un langage de programmation. Pour devenir populaire, un langage de programmation doit être le langage de script d'un système populaire. Fortran et Cobol étaient les langages de script des premiers mainframes IBM. C était le langage de script de Unix, et plus tard, Perl l'a été aussi. Tcl est le langage de script de Tk. Java et Javascript sont censés être les langages de script des navigateurs web.

Lisp n'est pas un langage massivement populaire car il n'est pas le langage de script d'un système massivement populaire. La popularité qu'il conserve remonte aux années 1960 et 1970, lorsqu'il était le langage de script du MIT. Beaucoup des grands programmeurs de l'époque étaient associés au MIT à un moment donné. Et au début des années 1970, avant C, le dialecte de Lisp du MIT, appelé MacLisp, était l'un des seuls langages de programmation qu'un hacker sérieux voudrait utiliser.

Aujourd'hui, Lisp est le langage de script de deux systèmes modérément populaires, Emacs et Autocad, et pour cette raison, je soupçonne que la plupart de la programmation Lisp faite aujourd'hui se fait en Emacs Lisp ou AutoLisp.

Les langages de programmation n'existent pas en isolation. Hacker est un verbe transitif — les hackers sont généralement en train de hacker quelque chose — et en pratique, les langages sont jugés par rapport à ce qu'ils sont utilisés pour hacker. Donc, si vous voulez concevoir un langage populaire, vous devez soit fournir plus qu'un langage, soit concevoir votre langage pour remplacer le langage de script d'un système existant.

Common Lisp est impopulaire en partie parce qu'il est un orphelin. Il est à l'origine venu avec un système à hacker : la machine Lisp. Mais les machines Lisp (avec les ordinateurs parallèles) ont été écrasées par la puissance croissante des processeurs à usage général dans les années 1980. Common Lisp aurait pu rester populaire s'il avait été un bon langage de script pour Unix. C'est, hélas, un langage atrocement mauvais.

Une façon de décrire cette situation est de dire qu'un langage n'est pas jugé sur ses propres mérites. Une autre vue est qu'un langage de programmation n'est vraiment pas un langage de programmation à moins qu'il ne soit aussi le langage de script de quelque chose. Cela ne semble injuste que si cela vient comme une surprise. Je pense que ce n'est pas plus injuste que d'attendre d'un langage de programmation qu'il ait, disons, une implémentation. C'est juste une partie de ce qu'est un langage de programmation.

Un langage de programmation a besoin d'une bonne implémentation, bien sûr, et cela doit être gratuit. Les entreprises paieront pour des logiciels, mais les hackers individuels ne le feront pas, et ce sont les hackers que vous devez attirer.

Un langage doit également avoir un livre à son sujet. Le livre doit être mince, bien écrit et plein de bons exemples. K&R est l'idéal ici. En ce moment, je dirais presque qu'un langage doit avoir un livre publié par O'Reilly. Cela devient le test de l'importance pour les hackers.

Il devrait également y avoir une documentation en ligne. En fait, le livre peut commencer comme une documentation en ligne. Mais je ne pense pas que les livres physiques soient encore obsolètes. Leur format est pratique, et la censure de facto imposée par les éditeurs est un filtre utile, bien que imparfait. Les librairies sont l'un des endroits les plus importants pour apprendre de nouveaux langages.

3 Brièveté

Étant donné que vous pouvez fournir les trois choses dont a besoin un langage — une implémentation gratuite, un livre et quelque chose à hacker — comment faites-vous pour créer un langage que les hackers aimeront ?

Une chose que les hackers aiment, c'est la brièveté. Les hackers sont paresseux, de la même manière que les mathématiciens et les architectes modernistes sont paresseux : ils détestent tout ce qui est superflu. Il ne serait pas loin de la vérité de dire qu'un hacker sur le point d'écrire un programme décide quel langage utiliser, du moins de manière subconsciente, en fonction du nombre total de caractères qu'il devra taper. Si ce n'est pas précisément ainsi que les hackers pensent, un concepteur de langage ferait bien d'agir comme si c'était le cas.

C'est une erreur d'essayer de dorloter l'utilisateur avec des expressions verbeuses qui sont censées ressembler à l'anglais. Cobol est notoire pour ce défaut. Un hacker considérerait qu'on lui demande d'écrire

ajouter x à y donnant z

au lieu de

z = x+y

comme quelque chose entre une insulte à son intelligence et un péché contre Dieu.

Il a parfois été dit que Lisp devrait utiliser first et rest au lieu de car et cdr, car cela rendrait les programmes plus faciles à lire. Peut-être pendant les premières heures. Mais un hacker peut apprendre assez rapidement que car signifie le premier élément d'une liste et cdr signifie le reste. Utiliser first et rest signifie 50 % de frappe en plus. Et ils sont également de longueurs différentes, ce qui signifie que les arguments ne s'aligneront pas lorsqu'ils seront appelés, comme car et cdr le sont souvent, dans des lignes successives. J'ai constaté qu'il est très important que le code s'aligne sur la page. Je peux à peine lire le code Lisp lorsqu'il est écrit dans une police à largeur variable, et des amis disent que c'est vrai pour d'autres langages aussi.

La brièveté est un domaine où les langages fortement typés perdent. Toutes choses étant égales par ailleurs, personne ne veut commencer un programme avec une multitude de déclarations. Tout ce qui peut être implicite, devrait l'être.

Les tokens individuels devraient également être courts. Perl et Common Lisp occupent des pôles opposés sur cette question. Les programmes Perl peuvent être presque cryptiquement denses, tandis que les noms des opérateurs intégrés de Common Lisp sont comiquement longs. Les concepteurs de Common Lisp s'attendaient probablement à ce que les utilisateurs aient des éditeurs de texte qui taperaient ces longs noms pour eux. Mais le coût d'un long nom n'est pas seulement le coût de le taper. Il y a aussi le coût de le lire, et le coût de l'espace qu'il occupe sur votre écran.

4 Hackabilité

Il y a une chose plus importante que la brièveté pour un hacker : pouvoir faire ce que vous voulez. Dans l'histoire des langages de programmation, une quantité surprenante d'efforts a été consacrée à empêcher les programmeurs de faire des choses considérées comme inappropriées. C'est un plan dangereusement présomptueux. Comment le concepteur de langage peut-il savoir ce dont le programmeur aura besoin ? Je pense que les concepteurs de langages feraient mieux de considérer leur utilisateur cible comme un génie qui aura besoin de faire des choses qu'ils n'avaient jamais anticipées, plutôt que comme un maladroit qui a besoin d'être protégé de lui-même. Le maladroit se tirera dans le pied de toute façon. Vous pouvez le sauver de faire référence à des variables dans un autre package, mais vous ne pouvez pas le sauver d'écrire un programme mal conçu pour résoudre le mauvais problème, et de prendre une éternité pour le faire.

Les bons programmeurs veulent souvent faire des choses dangereuses et peu recommandables. Par peu recommandable, je veux dire des choses qui vont au-delà de ce que la façade sémantique que le langage essaie de présenter : obtenir la représentation interne de certaines abstractions de haut niveau, par exemple. Les hackers aiment hacker, et hacker signifie entrer dans les choses et deviner ce que le concepteur original avait en tête.

Laissez-vous être deviné. Lorsque vous créez un outil, les gens l'utilisent de manière que vous n'aviez pas prévue, et cela est particulièrement vrai pour un outil hautement articulé comme un langage de programmation. Beaucoup de hackers voudront ajuster votre modèle sémantique d'une manière que vous n'avez jamais imaginée. Je dis, laissez-les ; donnez au programmeur accès à autant de choses internes que vous le pouvez sans mettre en danger des systèmes d'exécution comme le ramasse-miettes.

Dans Common Lisp, j'ai souvent voulu itérer à travers les champs d'une structure — pour éliminer les références à un objet supprimé, par exemple, ou trouver des champs qui ne sont pas initialisés. Je sais que les structures ne sont que des vecteurs en dessous. Et pourtant, je ne peux pas écrire une fonction à usage général que je peux appeler sur n'importe quelle structure. Je ne peux accéder aux champs que par leur nom, car c'est ce que signifie une structure.

Un hacker peut vouloir subvertir le modèle prévu des choses une ou deux fois dans un grand programme. Mais quelle différence cela fait de pouvoir le faire. Et cela peut être plus qu'une simple question de résoudre un problème. Il y a aussi un certain plaisir ici. Les hackers partagent le plaisir secret du chirurgien à fouiller dans les entrailles, le plaisir secret de l'adolescent à percer des boutons. [2] Pour les garçons, du moins, certains types d'horreurs sont fascinants. Le magazine Maxim publie un volume annuel de photographies, contenant un mélange de pin-ups et d'accidents horribles. Ils connaissent leur public.

Historiquement, Lisp a été bon pour laisser les hackers faire ce qu'ils veulent. La correction politique de Common Lisp est une aberration. Les premiers Lisps vous laissaient mettre la main sur tout. Une bonne partie de cet esprit est, heureusement, préservée dans les macros. Quelle chose merveilleuse, de pouvoir faire des transformations arbitraires sur le code source.

Les macros classiques sont un véritable outil de hacker — simples, puissantes et dangereuses. Il est si facile de comprendre ce qu'elles font : vous appelez une fonction sur les arguments de la macro, et tout ce qu'elle retourne est inséré à la place de l'appel de la macro. Les macros hygiéniques incarnent le principe opposé. Elles essaient de vous protéger de comprendre ce qu'elles font. Je n'ai jamais entendu les macros hygiéniques expliquées en une phrase. Et elles sont un exemple classique des dangers de décider ce que les programmeurs sont autorisés à vouloir. Les macros hygiéniques sont censées me protéger de la capture de variable, entre autres choses, mais la capture de variable est exactement ce que je veux dans certaines macros.

Un langage vraiment bon devrait être à la fois propre et sale : proprement conçu, avec un petit noyau d'opérateurs bien compris et hautement orthogonaux, mais sale dans le sens où il laisse les hackers faire ce qu'ils veulent. C est comme ça. Les premiers Lisps l'étaient aussi. Un langage de hacker aura toujours un caractère légèrement désinvolte.

Un bon langage de programmation devrait avoir des caractéristiques qui font que les gens qui utilisent l'expression "ingénierie logicielle" secouent la tête désapprobativement. À l'autre extrémité du continuum se trouvent des langages comme Ada et Pascal, modèles de décence qui sont bons pour l'enseignement et pas grand-chose d'autre.

5 Programmes Jetables

Pour être attrayant pour les hackers, un langage doit être bon pour écrire les types de programmes qu'ils veulent écrire. Et cela signifie, peut-être de manière surprenante, qu'il doit être bon pour écrire des programmes jetables.

Un programme jetable est un programme que vous écrivez rapidement pour une tâche limitée : un programme pour automatiser une tâche d'administration système, ou générer des données de test pour une simulation, ou convertir des données d'un format à un autre. La chose surprenante à propos des programmes jetables est que, comme les bâtiments "temporaires" construits dans tant d'universités américaines pendant la Seconde Guerre mondiale, ils ne sont souvent pas jetés. Beaucoup évoluent en de vrais programmes, avec de vraies fonctionnalités et de vrais utilisateurs.

J'ai l'intuition que les meilleurs grands programmes commencent leur vie de cette manière, plutôt que d'être conçus grands dès le départ, comme le barrage Hoover. C'est terrifiant de construire quelque chose de grand à partir de zéro. Lorsque les gens entreprennent un projet trop grand, ils se sentent dépassés. Le projet soit s'enlise, soit le résultat est stérile et rigide : un centre commercial plutôt qu'un vrai centre-ville, Brasilia plutôt que Rome, Ada plutôt que C.

Une autre façon d'obtenir un grand programme est de commencer par un programme jetable et de continuer à l'améliorer. Cette approche est moins décourageante, et la conception du programme bénéficie de l'évolution. Je pense que, si l'on regardait, cela se révélerait être la façon dont la plupart des grands programmes ont été développés. Et ceux qui ont évolué de cette manière sont probablement encore écrits dans le langage dans lequel ils ont été d'abord écrits, car il est rare qu'un programme soit porté, sauf pour des raisons politiques. Et donc, paradoxalement, si vous voulez créer un langage qui est utilisé pour de grands systèmes, vous devez le rendre bon pour écrire des programmes jetables, car c'est de là que viennent les grands systèmes.

Perl est un exemple frappant de cette idée. Il n'a pas seulement été conçu pour écrire des programmes jetables, mais était en fait un programme jetable lui-même. Perl a commencé sa vie comme une collection d'utilitaires pour générer des rapports, et n'est devenu un langage de programmation que lorsque les programmes jetables que les gens écrivaient en lui sont devenus plus grands. Ce n'est qu'à partir de Perl 5 (si ce n'est pas avant) que le langage était adapté à l'écriture de programmes sérieux, et pourtant il était déjà massivement populaire.

Qu'est-ce qui rend un langage bon pour les programmes jetables ? Pour commencer, il doit être facilement disponible. Un programme jetable est quelque chose que vous vous attendez à écrire en une heure. Donc, le langage doit probablement déjà être installé sur l'ordinateur que vous utilisez. Ce ne peut pas être quelque chose que vous devez installer avant de l'utiliser. Il doit être là. C était là parce qu'il venait avec le système d'exploitation. Perl était là parce qu'il était à l'origine un outil pour les administrateurs système, et le vôtre l'avait déjà installé.

Être disponible signifie plus que d'être installé, cependant. Un langage interactif, avec une interface en ligne de commande, est plus disponible qu'un langage que vous devez compiler et exécuter séparément. Un langage de programmation populaire devrait être interactif et démarrer rapidement.

Une autre chose que vous voulez dans un programme jetable est la brièveté. La brièveté est toujours attrayante pour les hackers, et jamais plus que dans un programme qu'ils s'attendent à produire en une heure.

6 Bibliothèques

Bien sûr, le summum de la brièveté est d'avoir le programme déjà écrit pour vous, et de simplement l'appeler. Et cela nous amène à ce que je pense être une caractéristique de plus en plus importante des langages de programmation : les fonctions de bibliothèque. Perl gagne parce qu'il a de grandes bibliothèques pour manipuler des chaînes. Cette classe de fonctions de bibliothèque est particulièrement importante pour les programmes jetables, qui sont souvent à l'origine écrits pour convertir ou extraire des données. Beaucoup de programmes Perl commencent probablement par juste quelques appels de bibliothèque assemblés.

Je pense qu'une grande partie des avancées qui se produiront dans les langages de programmation au cours des cinquante prochaines années aura à voir avec les fonctions de bibliothèque. Je pense que les futurs langages de programmation auront des bibliothèques aussi soigneusement conçues que le langage de base. La conception des langages de programmation ne portera pas sur la question de savoir s'il faut rendre votre langage fortement ou faiblement typé, orienté objet, fonctionnel, ou autre, mais sur la façon de concevoir de grandes bibliothèques. Le genre de concepteurs de langages qui aiment réfléchir à la façon de concevoir des systèmes de types peuvent frémir à cela. C'est presque comme écrire des applications ! Dommage. Les langages sont pour les programmeurs, et les bibliothèques sont ce dont les programmeurs ont besoin.

Il est difficile de concevoir de bonnes bibliothèques. Ce n'est pas simplement une question d'écrire beaucoup de code. Une fois que les bibliothèques deviennent trop grandes, il peut parfois prendre plus de temps de trouver la fonction dont vous avez besoin que d'écrire le code vous-même. Les bibliothèques doivent être conçues en utilisant un petit ensemble d'opérateurs orthogonaux, tout comme le langage de base. Il devrait être possible pour le programmeur de deviner quel appel de bibliothèque fera ce dont il a besoin.

Les bibliothèques sont un domaine où Common Lisp est en retard. Il n'y a que des bibliothèques rudimentaires pour manipuler des chaînes, et presque aucune pour communiquer avec le système d'exploitation. Pour des raisons historiques, Common Lisp essaie de prétendre que le système d'exploitation n'existe pas. Et parce que vous ne pouvez pas parler au système d'exploitation, vous êtes peu susceptible de pouvoir écrire un programme sérieux en n'utilisant que les opérateurs intégrés de Common Lisp. Vous devez également utiliser quelques hacks spécifiques à l'implémentation, et en pratique, ceux-ci tendent à ne pas vous donner tout ce que vous voulez. Les hackers penseraient beaucoup plus hautement de Lisp si Common Lisp avait de puissantes bibliothèques de chaînes et un bon support du système d'exploitation.

7 Syntaxe

Un langage avec la syntaxe de Lisp, ou plus précisément, le manque de syntaxe de Lisp, pourrait-il un jour devenir populaire ? Je ne sais pas la réponse à cette question. Je pense cependant que la syntaxe n'est pas la principale raison pour laquelle Lisp n'est actuellement pas populaire. Common Lisp a des problèmes plus graves que la syntaxe peu familière. Je connais plusieurs programmeurs qui sont à l'aise avec la syntaxe préfixe et qui utilisent pourtant Perl par défaut, car il a de puissantes bibliothèques de chaînes et peut parler au système d'exploitation.

Il y a deux problèmes possibles avec la notation préfixe : qu'elle est peu familière pour les programmeurs, et qu'elle n'est pas assez dense. La sagesse conventionnelle dans le monde de Lisp est que le premier problème est le vrai. Je ne suis pas si sûr. Oui, la notation préfixe fait paniquer les programmeurs ordinaires. Mais je ne pense pas que les opinions des programmeurs ordinaires comptent. Les langages deviennent populaires ou impopulaires en fonction de ce que les hackers experts en pensent, et je pense que les hackers experts pourraient être capables de gérer la notation préfixe. La syntaxe de Perl peut être assez incompréhensible, mais cela n'a pas entravé la popularité de Perl. Si quoi que ce soit, cela a peut-être aidé à favoriser un culte Perl.

Un problème plus sérieux est la diffusivité de la notation préfixe. Pour les hackers experts, c'est vraiment un problème. Personne ne veut écrire (aref a x y) quand il pourrait écrire a[x,y].

Dans ce cas particulier, il y a un moyen de contourner le problème. Si nous traitons les structures de données comme si elles étaient des fonctions sur des index, nous pourrions écrire (a x y) à la place, ce qui est encore plus court que la forme Perl. Des astuces similaires peuvent raccourcir d'autres types d'expressions.

Nous pouvons nous débarrasser de (ou rendre optionnelles) beaucoup de parenthèses en rendant l'indentation significative. C'est ainsi que les programmeurs lisent le code de toute façon : lorsque l'indentation dit une chose et que les délimiteurs en disent une autre, nous nous fions à l'indentation. Traiter l'indentation comme significative éliminerait cette source commune de bogues tout en rendant les programmes plus courts.

Parfois, la syntaxe infixe est plus facile à lire. C'est particulièrement vrai pour les expressions mathématiques. J'ai utilisé Lisp toute ma vie de programmeur et je ne trouve toujours pas les expressions mathématiques préfixes naturelles. Et pourtant, il est pratique, surtout lorsque vous générez du code, d'avoir des opérateurs qui prennent n'importe quel nombre d'arguments. Donc, si nous avons une syntaxe infixe, elle devrait probablement être implémentée comme une sorte de macro de lecture.

Je ne pense pas que nous devrions être religieusement opposés à l'introduction de la syntaxe dans Lisp, tant qu'elle se traduit d'une manière bien comprise en s-expressions sous-jacentes. Il y a déjà pas mal de syntaxe dans Lisp. Ce n'est pas nécessairement mauvais d'en introduire davantage, tant que personne n'est contraint de l'utiliser. Dans Common Lisp, certains délimiteurs sont réservés au langage, suggérant qu'au moins certains des concepteurs avaient l'intention d'avoir plus de syntaxe à l'avenir.

L'un des éléments de syntaxe les plus scandaleusement non-lisp dans Common Lisp se trouve dans les chaînes de format ; format est un langage à part entière, et ce langage n'est pas Lisp. S'il y avait un plan pour introduire plus de syntaxe dans Lisp, les spécificateurs de format pourraient être inclus. Ce serait une bonne chose si les macros pouvaient générer des spécificateurs de format de la manière dont elles génèrent tout autre type de code.

Un éminent hacker Lisp m'a dit que sa copie de CLTL s'ouvre sur la section format. La mienne aussi. Cela indique probablement une marge d'amélioration. Cela peut aussi signifier que les programmes font beaucoup d'E/S.

8 Efficacité

Un bon langage, comme tout le monde le sait, devrait générer du code rapide. Mais en pratique, je ne pense pas que le code rapide provienne principalement des choses que vous faites dans la conception du langage. Comme Knuth l'a souligné il y a longtemps, la vitesse n'a d'importance que dans certains goulets d'étranglement critiques. Et comme de nombreux programmeurs l'ont observé depuis, on se trompe très souvent sur l'endroit où se trouvent ces goulets d'étranglement.

Donc, en pratique, la façon d'obtenir du code rapide est d'avoir un très bon profileur, plutôt que de, disons, rendre le langage fortement typé. Vous n'avez pas besoin de connaître le type de chaque argument dans chaque appel dans le programme. Vous devez être capable de déclarer les types d'arguments dans les goulets d'étranglement. Et encore plus, vous devez être capable de découvrir où se trouvent les goulets d'étranglement.

Une plainte que les gens ont eue avec Lisp est qu'il est difficile de dire ce qui est coûteux. Cela pourrait être vrai. Cela pourrait aussi être inévitable, si vous voulez avoir un langage très abstrait. Et dans tous les cas, je pense qu'un bon profilage irait loin pour résoudre le problème : vous apprendriez rapidement ce qui était coûteux.

Une partie du problème ici est sociale. Les concepteurs de langages aiment écrire des compilateurs rapides. C'est ainsi qu'ils mesurent leur compétence. Ils considèrent le profileur comme un ajout, au mieux. Mais en pratique, un bon profileur peut faire plus pour améliorer la vitesse des programmes réels écrits dans le langage qu'un compilateur qui génère du code rapide. Ici encore, les concepteurs de langages sont quelque peu déconnectés de leurs utilisateurs. Ils font un très bon travail pour résoudre légèrement le mauvais problème.

Il pourrait être judicieux d'avoir un profileur actif — pour pousser les données de performance au programmeur au lieu d'attendre qu'il vienne les demander. Par exemple, l'éditeur pourrait afficher les goulets d'étranglement en rouge lorsque le programmeur édite le code source. Une autre approche serait de représenter d'une manière ou d'une autre ce qui se passe dans les programmes en cours d'exécution. Cela serait particulièrement bénéfique dans les applications basées sur des serveurs, où vous avez beaucoup de programmes en cours d'exécution à examiner. Un profileur actif pourrait montrer graphiquement ce qui se passe en mémoire pendant qu'un programme s'exécute, ou même émettre des sons qui indiquent ce qui se passe.

Le son est un bon indice de problèmes. Dans un endroit où j'ai travaillé, nous avions un grand tableau de cadrans montrant ce qui arrivait à nos serveurs web. Les aiguilles étaient déplacées par de petits servomoteurs qui émettaient un léger bruit lorsqu'ils tournaient. Je ne pouvais pas voir le tableau depuis mon bureau, mais j'ai découvert que je pouvais dire immédiatement, par le son, lorsqu'il y avait un problème avec un serveur.

Il pourrait même être possible d'écrire un profileur qui détecterait automatiquement les algorithmes inefficaces. Je ne serais pas surpris si certains modèles d'accès à la mémoire s'avéraient être des signes sûrs de mauvais algorithmes. S'il y avait un petit bonhomme qui courait à l'intérieur de l'ordinateur en exécutant nos programmes, il aurait probablement une histoire aussi longue et plaintive à raconter sur son travail qu'un employé du gouvernement fédéral. J'ai souvent l'impression que j'envoie le processeur dans beaucoup de chasses aux oies sauvages, mais je n'ai jamais eu de bon moyen de voir ce qu'il fait.

Un certain nombre de Lisps compilent maintenant en bytecode, qui est ensuite exécuté par un interpréteur. Cela se fait généralement pour faciliter le portage de l'implémentation, mais cela pourrait être une fonctionnalité utile du langage. Il pourrait être judicieux de faire du bytecode une partie officielle du langage, et de permettre aux programmeurs d'utiliser du bytecode en ligne dans les goulets d'étranglement. Ainsi, de telles optimisations seraient également portables.

La nature de la vitesse, telle que perçue par l'utilisateur final, pourrait être en train de changer. Avec l'essor des applications basées sur des serveurs, de plus en plus de programmes pourraient s'avérer être liés à l'E/S. Il vaudra la peine de rendre l'E/S rapide. Le langage peut aider avec des mesures simples comme des fonctions de sortie formatées simples et rapides, et aussi avec des changements structurels profonds comme le caching et les objets persistants.

Les utilisateurs s'intéressent au temps de réponse. Mais un autre type d'efficacité sera de plus en plus important : le nombre d'utilisateurs simultanés que vous pouvez prendre en charge par processeur. Beaucoup des applications intéressantes écrites dans un avenir proche seront basées sur des serveurs, et le nombre d'utilisateurs par serveur est la question critique pour quiconque hébergeant de telles applications. Dans le coût d'investissement d'une entreprise offrant une application basée sur un serveur, c'est le diviseur.

Pendant des années, l'efficacité n'a pas beaucoup compté dans la plupart des applications destinées aux utilisateurs finaux. Les développeurs ont pu supposer que chaque utilisateur disposerait d'un processeur de plus en plus puissant sur son bureau. Et selon la loi de Parkinson, les logiciels se sont étendus pour utiliser les ressources disponibles. Cela changera avec les applications basées sur des serveurs. Dans ce monde, le matériel et les logiciels seront fournis ensemble. Pour les entreprises qui offrent des applications basées sur des serveurs, cela fera une très grande différence pour le résultat final combien d'utilisateurs elles peuvent prendre en charge par serveur.

Dans certaines applications, le processeur sera le facteur limitant, et la vitesse d'exécution sera la chose la plus importante à optimiser. Mais souvent, la mémoire sera la limite ; le nombre d'utilisateurs simultanés sera déterminé par la quantité de mémoire dont vous avez besoin pour les données de chaque utilisateur. Le langage peut également aider ici. Un bon support pour les threads permettra à tous les utilisateurs de partager un seul tas. Il peut également être utile d'avoir des objets persistants et/ou un support au niveau du langage pour le chargement paresseux.

9 Temps

Le dernier ingrédient dont un langage populaire a besoin est le temps. Personne ne veut écrire des programmes dans un langage qui pourrait disparaître, comme tant de langages de programmation le font. Donc, la plupart des hackers auront tendance à attendre qu'un langage soit présent depuis quelques années avant même de considérer son utilisation.

Les inventeurs de choses merveilleuses sont souvent surpris de découvrir cela, mais vous avez besoin de temps pour faire passer un message aux gens. Un ami à moi ne fait presque jamais quoi que ce soit la première fois que quelqu'un lui demande. Il sait que les gens demandent parfois des choses qu'ils ne veulent finalement pas. Pour éviter de perdre son temps, il attend la troisième ou la quatrième fois qu'on lui demande de faire quelque chose ; d'ici là, celui qui demande peut être assez agacé, mais au moins, ils veulent probablement vraiment ce qu'ils demandent.

La plupart des gens ont appris à faire un filtrage similaire sur les nouvelles choses dont ils entendent parler. Ils ne commencent même pas à prêter attention jusqu'à ce qu'ils aient entendu parler de quelque chose dix fois. Ils sont parfaitement justifiés : la majorité des nouvelles choses à la mode s'avèrent être une perte de temps, et finissent par disparaître. En retardant l'apprentissage de VRML, j'ai évité d'avoir à l'apprendre du tout.

Donc, quiconque invente quelque chose de nouveau doit s'attendre à devoir répéter son message pendant des années avant que les gens commencent à le comprendre. Nous avons écrit ce qui était, autant que je sache, la première application basée sur un serveur web, et il nous a fallu des années pour faire comprendre aux gens qu'elle n'avait pas besoin d'être téléchargée. Ce n'était pas qu'ils étaient stupides. Ils nous avaient simplement ignorés.

La bonne nouvelle est que la simple répétition résout le problème. Tout ce que vous avez à faire est de continuer à raconter votre histoire, et finalement les gens commenceront à écouter. Ce n'est pas quand les gens remarquent que vous êtes là qu'ils prêtent attention ; c'est quand ils remarquent que vous êtes toujours là.

C'est tout aussi bien qu'il faille généralement un certain temps pour prendre de l'élan. La plupart des technologies évoluent beaucoup même après leur lancement initial — les langages de programmation en particulier. Rien ne pourrait être mieux, pour une nouvelle technologie, que quelques années d'utilisation uniquement par un petit nombre de premiers utilisateurs. Les premiers utilisateurs sont sophistiqués et exigeants, et font rapidement ressortir les défauts qui subsistent dans votre technologie. Lorsque vous n'avez que quelques utilisateurs, vous pouvez être en contact étroit avec tous. Et les premiers utilisateurs sont indulgents lorsque vous améliorez votre système, même si cela entraîne quelques ruptures.

Il y a deux façons d'introduire une nouvelle technologie : la méthode de croissance organique et la méthode du big bang. La méthode de croissance organique est illustrée par le classique démarrage sous-financé dans un garage. Quelques gars, travaillant dans l'obscurité, développent une nouvelle technologie. Ils la lancent sans marketing et ont initialement seulement quelques utilisateurs (fanatiquement dévoués). Ils continuent à améliorer la technologie, et pendant ce temps, leur base d'utilisateurs grandit par le bouche-à-oreille. Avant qu'ils ne s'en rendent compte, ils sont devenus grands.

L'autre approche, la méthode du big bang, est illustrée par le démarrage soutenu par des investisseurs en capital-risque, fortement commercialisé. Ils se précipitent pour développer un produit, le lancent avec une grande publicité, et espèrent immédiatement avoir une large base d'utilisateurs.

En général, les gars du garage envient les gars du big bang. Les gars du big bang sont lisses, confiants et respectés par les investisseurs en capital-risque. Ils peuvent se permettre le meilleur de tout, et la campagne de relations publiques entourant le lancement a pour effet secondaire de les rendre célèbres. Les gars de la croissance organique, assis dans leur garage, se sentent pauvres et non aimés. Et pourtant, je pense qu'ils ont souvent tort de se sentir désolés pour eux-mêmes. La croissance organique semble produire une meilleure technologie et des fondateurs plus riches que la méthode du big bang. Si vous regardez les technologies dominantes aujourd'hui, vous constaterez que la plupart d'entre elles ont évolué de manière organique.

Ce modèle ne s'applique pas seulement aux entreprises. Vous le voyez aussi dans la recherche sponsorisée. Multics et Common Lisp étaient des projets de big bang, et Unix et MacLisp étaient des projets de croissance organique.

10 Redesign

"Le meilleur écriture est la réécriture," a écrit E. B. White. Chaque bon écrivain le sait, et c'est vrai pour les logiciels aussi. La partie la plus importante de la conception est la redéfinition. Les langages de programmation, en particulier, ne sont pas redessinés assez souvent.

Pour écrire un bon logiciel, vous devez simultanément garder deux idées opposées dans votre tête. Vous avez besoin de la foi naïve du jeune hacker en ses capacités, et en même temps du scepticisme du vétéran. Vous devez être capable de penser à quel point cela peut-il être difficile ? d'un côté de votre cerveau tout en pensant cela ne fonctionnera jamais de l'autre.

Le truc est de réaliser qu'il n'y a pas de véritable contradiction ici. Vous voulez être optimiste et sceptique à propos de deux choses différentes. Vous devez être optimiste quant à la possibilité de résoudre le problème, mais sceptique quant à la valeur de la solution que vous avez jusqu'à présent.

Les personnes qui font du bon travail pensent souvent que ce sur quoi elles travaillent n'est pas bon. D'autres voient ce qu'elles ont fait et sont pleines d'émerveillement, mais le créateur est plein d'inquiétude. Ce modèle n'est pas une coïncidence : c'est l'inquiétude qui a rendu le travail bon.

Si vous pouvez garder l'espoir et l'inquiétude en équilibre, ils propulseront un projet de la même manière que vos deux jambes propulsent un vélo. Dans la première phase du moteur d'innovation à deux cycles, vous travaillez furieusement sur un problème, inspiré par votre confiance que vous serez capable de le résoudre. Dans la deuxième phase, vous regardez ce que vous avez fait à la lumière froide du matin, et voyez tous ses défauts très clairement. Mais tant que votre esprit critique ne l'emporte pas sur votre espoir, vous serez capable de regarder votre système, certes incomplet, et de penser, à quel point cela peut-il être difficile d'aller jusqu'au bout ?, continuant ainsi le cycle.

Il est délicat de garder les deux forces en équilibre. Chez les jeunes hackers, l'optimisme prédomine. Ils produisent quelque chose, sont convaincus que c'est génial, et ne l'améliorent jamais. Chez les vieux hackers, le scepticisme prédomine, et ils n'oseront même pas entreprendre des projets ambitieux.

Tout ce que vous pouvez faire pour maintenir le cycle de redéfinition en cours est bon. La prose peut être réécrite encore et encore jusqu'à ce que vous en soyez satisfait. Mais les logiciels, en règle générale, ne sont pas redessinés assez souvent. La prose a des lecteurs, mais les logiciels ont des utilisateurs. Si un écrivain réécrit un essai, les personnes qui ont lu l'ancienne version sont peu susceptibles de se plaindre que leurs pensées ont été brisées par une incompatibilité nouvellement introduite.

Les utilisateurs sont une épée à double tranchant. Ils peuvent vous aider à améliorer votre langage, mais ils peuvent aussi vous dissuader de l'améliorer. Donc, choisissez vos utilisateurs avec soin, et soyez lent à augmenter leur nombre. Avoir des utilisateurs est comme l'optimisation : la voie sage est de la retarder. De plus, en règle générale, vous pouvez à tout moment vous en tirer en changeant plus que vous ne le pensez. Introduire un changement est comme retirer un bandage : la douleur est un souvenir presque aussi vite que vous la ressentez.

Tout le monde sait qu'il n'est pas bon d'avoir un langage conçu par un comité. Les comités produisent de mauvaises conceptions. Mais je pense que le pire danger des comités est qu'ils interfèrent avec la redéfinition. C'est tellement de travail d'introduire des changements que personne ne veut s'en donner la peine. Quoi que décide un comité, cela a tendance à rester ainsi, même si la plupart des membres ne l'aiment pas.

Même un comité de deux gêne la redéfinition. Cela se produit particulièrement dans les interfaces entre des morceaux de logiciels écrits par deux personnes différentes. Pour changer l'interface, les deux doivent convenir de la changer en même temps. Et donc les interfaces ont tendance à ne pas changer du tout, ce qui est un problème car elles ont tendance à être l'une des parties les plus ad hoc de tout système.

Une solution ici pourrait être de concevoir des systèmes de sorte que les interfaces soient horizontales plutôt que verticales — de sorte que les modules soient toujours empilés verticalement en strates d'abstraction. Alors l'interface aura tendance à être possédée par l'un d'eux. Le niveau inférieur de deux niveaux sera soit un langage dans lequel le supérieur est écrit, auquel cas le niveau inférieur possédera l'interface, soit il sera un esclave, auquel cas l'interface pourra être dictée par le niveau supérieur.

11 Lisp

Tout cela implique qu'il y a de l'espoir pour un nouveau Lisp. Il y a de l'espoir pour tout langage qui donne aux hackers ce qu'ils veulent, y compris Lisp. Je pense que nous avons peut-être fait une erreur en pensant que les hackers sont rebutés par l'étrangeté de Lisp. Cette illusion réconfortante a peut-être empêché de voir le véritable problème avec Lisp, ou du moins Common Lisp, qui est qu'il est mauvais pour faire ce que les hackers veulent faire. Un langage de hacker a besoin de bibliothèques puissantes et de quelque chose à hacker. Common Lisp n'a ni l'un ni l'autre. Un langage de hacker est concis et hackable. Common Lisp ne l'est pas.

La bonne nouvelle est que ce n'est pas Lisp qui est mauvais, mais Common Lisp. Si nous pouvons développer un nouveau Lisp qui est un véritable langage de hacker, je pense que les hackers l'utiliseront. Ils utiliseront n'importe quel langage qui fait le travail. Tout ce que nous avons à faire est de nous assurer que ce nouveau Lisp fait un travail important mieux que d'autres langages.

L'histoire offre un certain encouragement. Au fil du temps, de nouveaux langages de programmation successifs ont pris de plus en plus de caractéristiques de Lisp. Il ne reste plus grand-chose à copier avant que le langage que vous avez créé ne soit Lisp. Le dernier langage à la mode, Python, est un Lisp édulcoré avec une syntaxe infixe et sans macros. Un nouveau Lisp serait une étape naturelle dans cette progression.

Je pense parfois qu'il serait bon de marketing de l'appeler une version améliorée de Python. Cela sonne plus branché que Lisp. Pour beaucoup de gens, Lisp est un langage d'IA lent avec beaucoup de parenthèses. La biographie officielle de Fritz Kunze évite soigneusement de mentionner le mot L. Mais je parie que nous ne devrions pas avoir peur d'appeler le nouveau Lisp Lisp. Lisp a encore beaucoup de respect latent parmi les meilleurs hackers — ceux qui ont suivi 6.001 et l'ont compris, par exemple. Et ce sont les utilisateurs que vous devez gagner.

Dans "Comment devenir un hacker", Eric Raymond décrit Lisp comme quelque chose comme le latin ou le grec — un langage que vous devriez apprendre comme un exercice intellectuel, même si vous ne l'utiliserez pas réellement :

Lisp vaut la peine d'être appris pour l'expérience d'illumination profonde que vous aurez lorsque vous le comprendrez enfin ; cette expérience fera de vous un meilleur programmeur pour le reste de vos jours, même si vous n'utilisez jamais vraiment beaucoup Lisp lui-même.

Si je ne connaissais pas Lisp, lire cela me ferait poser des questions. Un langage qui me rendrait un meilleur programmeur, si cela signifie quelque chose, signifie un langage qui serait meilleur pour la programmation. Et c'est en fait l'implication de ce qu'Eric dit.

Tant que cette idée flotte encore, je pense que les hackers seront suffisamment réceptifs à un nouveau Lisp, même s'il s'appelle Lisp. Mais ce Lisp doit être un langage de hacker, comme les Lisps classiques des années 1970. Il doit être concis, simple et hackable. Et il doit avoir de puissantes bibliothèques pour faire ce que les hackers veulent faire maintenant.

En ce qui concerne les bibliothèques, je pense qu'il y a de la place pour battre des langages comme Perl et Python à leur propre jeu. Beaucoup des nouvelles applications qui devront être écrites dans les années à venir seront des applications basées sur des serveurs. Il n'y a aucune raison qu'un nouveau Lisp ne devrait pas avoir des bibliothèques de chaînes aussi bonnes que Perl, et si ce nouveau Lisp avait également de puissantes bibliothèques pour les applications basées sur des serveurs, il pourrait être très populaire. Les vrais hackers ne tourneront pas le nez à un nouvel outil qui leur permettra de résoudre des problèmes difficiles avec quelques appels de bibliothèque. Rappelez-vous, les hackers sont paresseux.

Il pourrait être encore plus avantageux d'avoir un support de langage de base pour les applications basées sur des serveurs. Par exemple, un support explicite pour les programmes avec plusieurs utilisateurs, ou la propriété des données au niveau des balises de type.

Les applications basées sur des serveurs nous donnent également la réponse à la question de ce que ce nouveau Lisp sera utilisé pour hacker. Il ne ferait pas de mal de rendre Lisp meilleur en tant que langage de script pour Unix. (Il serait difficile de le rendre pire.) Mais je pense qu'il y a des domaines où les langages existants seraient plus faciles à battre. Je pense qu'il pourrait être préférable de suivre le modèle de Tcl, et de fournir le Lisp avec un système complet pour soutenir les applications basées sur des serveurs. Lisp est un ajustement naturel pour les applications basées sur des serveurs. Les fermetures lexicales fournissent un moyen d'obtenir l'effet des sous-routines lorsque l'interface utilisateur n'est qu'une série de pages web. Les s-expressions se mappent bien sur le html, et les macros sont bonnes pour le générer. Il doit y avoir de meilleurs outils pour écrire des applications basées sur des serveurs, et il doit y avoir un nouveau Lisp, et les deux fonctionneraient très bien ensemble.

12 Le Langage de Rêve

Pour résumer, essayons de décrire le langage de rêve du hacker. Le langage de rêve est beau, propre et concis. Il a un niveau supérieur interactif qui démarre rapidement. Vous pouvez écrire des programmes pour résoudre des problèmes courants avec très peu de code. Presque tout le code dans n'importe quel programme que vous écrivez est du code spécifique à votre application. Tout le reste a été fait pour vous.

La syntaxe du langage est brève à l'excès. Vous n'avez jamais à taper un caractère inutile, ni même à utiliser beaucoup la touche majuscule.

En utilisant de grandes abstractions, vous pouvez écrire la première version d'un programme très rapidement. Plus tard, lorsque vous souhaitez optimiser, il y a un très bon profileur qui vous indique où concentrer votre attention. Vous pouvez rendre les boucles internes aveuglantes de rapidité, même en écrivant du bytecode en ligne si vous en avez besoin.

Il y a beaucoup de bons exemples à apprendre, et le langage est suffisamment intuitif pour que vous puissiez apprendre à l'utiliser à partir d'exemples en quelques minutes. Vous n'avez pas besoin de beaucoup consulter le manuel. Le manuel est mince, et a peu d'avertissements et de qualifications.

Le langage a un petit noyau, et des bibliothèques puissantes et hautement orthogonales qui sont aussi soigneusement conçues que le langage de base. Les bibliothèques fonctionnent toutes bien ensemble ; tout dans le langage s'emboîte comme les pièces d'un bon appareil photo. Rien n'est obsolète, ou conservé pour des raisons de compatibilité. Le code source de toutes les bibliothèques est facilement disponible. Il est facile de parler au système d'exploitation et aux applications écrites dans d'autres langages.

Le langage est construit en couches. Les abstractions de niveau supérieur sont construites de manière très transparente à partir d'abstractions de niveau inférieur, que vous pouvez obtenir si vous le souhaitez.

Rien n'est caché pour vous qui ne doit absolument pas l'être. Le langage offre des abstractions uniquement comme moyen de vous faire gagner du travail, plutôt que comme moyen de vous dire quoi faire. En fait, le langage vous encourage à être un participant égal dans sa conception. Vous pouvez changer tout ce qui le concerne, y compris même sa syntaxe, et tout ce que vous écrivez a, autant que possible, le même statut que ce qui est prédéfini.

Notes

[1] Des macros très proches de l'idée moderne ont été proposées par Timothy Hart en 1964, deux ans après la sortie de Lisp 1.5. Ce qui manquait, au départ, c'étaient des moyens d'éviter la capture de variable et l'évaluation multiple ; les exemples de Hart sont sujets aux deux.

[2] Dans Quand l'air touche votre cerveau, le neurochirurgien Frank Vertosick raconte une conversation dans laquelle son résident principal, Gary, parle de la différence entre les chirurgiens et les internistes ("puces") :

Gary et moi avons commandé une grande pizza et trouvé une cabine ouverte. Le chef a allumé une cigarette. "Regardez ces putains de puces, jacassant sur une maladie qu'ils ne verront qu'une fois dans leur vie. C'est ça le problème avec les puces, elles n'aiment que les trucs bizarres. Elles détestent leurs cas de pain et de beurre. C'est la différence entre nous et ces putains de puces. Vous voyez, nous aimons les grosses hernies discales lombaires juteuses, mais elles détestent l'hypertension...."

Il est difficile de penser à une hernie discale lombaire comme à quelque chose de juteux (sauf littéralement). Et pourtant, je pense savoir ce qu'ils veulent dire. J'ai souvent eu un bug juteux à traquer. Quelqu'un qui n'est pas programmeur aurait du mal à imaginer qu'il puisse y avoir du plaisir dans un bug. Il est sûrement préférable que tout fonctionne simplement. D'une certaine manière, c'est le cas. Et pourtant, il y a indéniablement une satisfaction macabre à traquer certains types de bugs.