ÊTRE POPULAIRE
OriginalMai 2001
(Cet article a été écrit comme une sorte de plan d'affaires pour un nouveau langage. Il manque donc (parce qu'il tient pour acquis) la caractéristique la plus importante d'un bon langage de programmation : des abstractions très puissantes.)
Un de mes amis a un jour dit à un éminent expert des 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 que peu importe à quel point son langage serait bon, personne ne l'utiliserait. Du moins, c'est 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 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 de sémantique dénotationnelle ou de conception de compilateur) 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 uniquement en fonction de leurs mérites. La plupart des programmeurs se voient dire quelle langue utiliser par quelqu'un d'autre. Et pourtant je pense que l'effet de ces facteurs externes sur la popularité des langages de programmation n'est pas aussi grand qu'on le pense parfois. Je pense qu'un plus gros problème est que l'idée qu'un hacker se fait d'un bon langage de programmation n'est pas la même que celle de la plupart des concepteurs de langages.
Entre les deux, c'est l'opinion du hacker 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 faiblesses humaines autant que les chaussures doivent être conçues pour les pieds humains. Si une chaussure vous fait mal quand vous la mettez, c'est une mauvaise chaussure, si élégante soit-elle en tant qu'objet sculptural.
Il se peut que la majorité des programmeurs ne puissent pas distinguer un bon langage d'un mauvais. Mais c'est la même chose avec n'importe quel autre outil. Cela ne signifie pas que c'est une perte de temps 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 infime minorité, certes, mais c'est cette infime minorité qui écrit tous les bons logiciels, et leur influence est telle que le reste des programmeurs auront tendance à utiliser quel que soit le langage qu'ils utilisent. Souvent, en effet, ce n'est pas seulement une influence mais un ordre : souvent, les hackers experts sont les personnes mêmes qui, en tant que leurs patrons ou conseillers universitaires, 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 la hype (Ada, Java) jouent aussi un rôle - mais je pense que c'est la force la plus puissante à long terme. Avec une masse critique initiale et suffisamment de temps, un langage de programmation devient probablement à peu près aussi populaire qu'il le mérite. Et la popularité sépare davantage les bons langages des mauvais, car les retours d'expérience des vrais utilisateurs conduisent toujours à des améliorations. Regardez à quel point 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 les hackers du MIT aient passé quelques années à utiliser Lisp pour écrire de vrais programmes. [1]
Donc, qu'un langage doive être bon pour être populaire ou non, 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 matière de langages de programmation ne reste pas statique. Et pourtant, les Lisps que nous avons aujourd'hui sont encore à peu près ce qu'ils étaient au MIT au milieu des années 1980, car c'est la dernière fois que Lisp a eu 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 ? Par d'autres hackers. Mais il doit y avoir un groupe initial de hackers utilisant le langage pour que d'autres puissent même en entendre parler. Je me demande quelle doit être la taille de ce groupe ; combien d'utilisateurs constituent une masse critique ? En gros, je dirais vingt. Si un langage avait vingt utilisateurs distincts, c'est-à-dire vingt utilisateurs qui ont décidé d'eux-mêmes de l'utiliser, je le considérerais comme réel.
Y arriver ne peut pas être facile. Je ne serais pas surpris si c'était plus difficile d'aller 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 ordinateurs centraux IBM. C était le langage de script d'Unix, et plus tard, Perl l'a été aussi. Tcl est le langage de script de Tk. Java et Javascript sont destinés à être les langages de script des navigateurs web.
Lisp n'est pas un langage massivement populaire parce qu'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 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 d'aujourd'hui se fait en Emacs Lisp ou en AutoLisp.
Les langages de programmation n'existent pas dans l'isolement. Hacker est un verbe transitif - les hackers hackent généralement quelque chose - et dans la pratique, les langages sont jugés par rapport à ce qu'ils servent à 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 de quelque système existant.
Le Common Lisp est impopulaire en partie parce que c'est un orphelin. Il est vrai qu'il est venu à l'origine avec un système à pirater : la machine Lisp. Mais les machines Lisp (ainsi que les ordinateurs parallèles) ont été écrasées par la puissance croissante des processeurs à usage général dans les années 1980. Le Common Lisp aurait pu rester populaire s'il avait été un bon langage de script pour Unix. Hélas, c'est 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 de s'attendre à ce qu'un langage de programmation ait, disons, une implémentation. C'est juste une partie de ce qu'est un langage de programmation.
Un langage de programmation a bien sûr besoin d'une bonne implémentation, et celle-ci doit être gratuite. Les entreprises paieront pour un logiciel, mais les hackers individuels ne le feront pas, et ce sont les hackers dont vous avez besoin pour attirer.
Un langage doit également avoir un livre à son sujet. Le livre devrait être mince, bien écrit et rempli de bons exemples. K&R est l'idéal ici. Pour le moment, je dirais presque qu'un langage doit avoir un livre publié par O'Reilly. C'est en train de devenir le test pour compter pour les hackers.
Il devrait également y avoir une documentation en ligne. En fait, le livre peut commencer sous forme de documentation en ligne. Mais je ne pense pas que les livres physiques soient désuets pour le moment. Leur format est pratique, et la censure de facto imposée par les éditeurs est un filtre utile, même s'il est imparfait. Les librairies sont l'un des endroits les plus importants pour découvrir de nouveaux langages.
3 Brièveté
Étant donné que vous pouvez fournir les trois choses dont un langage a besoin - une implémentation gratuite, un livre et quelque chose à pirater - comment faites-vous 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 de la langue à utiliser, au 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 pensent les hackers, un concepteur de langage ferait bien d'agir comme si c'était le cas.
C'est une erreur d'essayer de chouchouter l'utilisateur avec des expressions longues et verbeuses censées ressembler à l'anglais. Le Cobol est tristement célèbre pour ce défaut. Un hacker considérerait le fait de lui demander d'écrire
add x to y giving z
au lieu de
z = x+y
comme quelque chose entre une insulte à son intelligence et un péché contre Dieu.
On a parfois dit que Lisp devrait utiliser first et rest au lieu de car et cdr, car cela rendrait les programmes plus faciles à lire. Peut-être pour les deux 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 ont également des 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, sur des lignes successives. J'ai constaté que l'alignement du code sur la page compte beaucoup. Je peux à peine lire le code Lisp lorsqu'il est dans une police à largeur variable, et des amis disent que c'est vrai pour d'autres langages aussi.
La brièveté est un endroit où les langages fortement typés perdent. Toutes choses étant égales par ailleurs, personne ne veut commencer un programme avec une série de déclarations. Tout ce qui peut être implicite, devrait l'être.
Les jetons 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 du Common Lisp sont comiquement longs. Les concepteurs du Common Lisp s'attendaient probablement à ce que les utilisateurs aient des éditeurs de texte qui tapent ces longs noms pour eux. Mais le coût d'un long nom n'est pas seulement le coût de la frappe. Il y a aussi le coût de la lecture 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 l'on veut. 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 du langage peut-il savoir ce dont le programmeur aura besoin de faire ? 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'ont jamais anticipées, plutôt que comme un maladroit qui a besoin d'être protégé de lui-même. Le maladroit se tirera de toute façon dans le pied. 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 mettre une éternité à le faire.
Les bons programmeurs veulent souvent faire des choses dangereuses et peu ragoûtantes. Par peu ragoûtantes, je veux dire des choses qui vont derrière quelconque façade sémantique que le langage essaie de présenter : obtenir la représentation interne d'une certaine abstraction de haut niveau, par exemple. Les hackers aiment pirater, et pirater signifie entrer dans les choses et deviner à l'envers le concepteur d'origine.
Laissez-vous deviner à l'envers. Lorsque vous fabriquez un outil, les gens l'utilisent de manières que vous n'aviez pas prévues, et c'est particulièrement vrai d'un outil très articulé comme un langage de programmation. De nombreux hackers voudront bidouiller votre modèle sémantique d'une manière que vous n'auriez jamais imaginée. Je dis, laissez-les faire ; donnez à l'programmeur l'accès à autant de choses internes que possible sans mettre en danger les systèmes d'exécution comme le ramasse-miettes.
En Common Lisp, j'ai souvent voulu itérer à travers les champs d'une struct - pour démêler les références à un objet supprimé, par exemple, ou trouver des champs qui ne sont pas initialisés. Je sais que les structs ne sont que des vecteurs en dessous. Et pourtant, je ne peux pas écrire une fonction générale que je peux appeler sur n'importe quelle struct. Je ne peux accéder aux champs que par leur nom, car c'est ce que signifie une struct.
Un hacker ne voudra peut-être subvertir le modèle prévu des choses qu'une ou deux fois dans un gros programme. Mais quelle différence cela fait de pouvoir le faire. Et ce peut être plus qu'une simple question de résolution d'un problème. Il y a aussi un certain plaisir ici. Les hackers partagent le plaisir secret du chirurgien à fouiner dans les entrailles brutes, le plaisir secret de l'adolescent à faire craquer les boutons. [2] Pour les garçons, du moins, certains types d'horreurs sont fascinants. Maxim magazine publie un volume annuel de photographies, contenant un mélange de pin-ups et d'accidents sanglants. Ils connaissent leur public.
Historiquement, Lisp a été bon pour laisser les hackers faire à leur guise. La correction politique de Common Lisp est une aberration. Les premiers Lisps vous ont permis de mettre la main sur tout. Une bonne partie de cet esprit est, heureusement, préservée dans les macros. Quelle chose merveilleuse, que de pouvoir effectuer 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 renvoie est inséré à la place de l'appel de macro. Les macros hygiéniques incarnent le principe opposé. Ils essaient de vous protéger de la compréhension de ce qu'ils font. Je n'ai jamais entendu les macros hygiéniques expliquées en une phrase. Et ce sont un exemple classique des dangers de décider de ce que les programmeurs sont autorisés à vouloir. Les macros hygiéniques sont destinées à me protéger de la capture de variables, entre autres choses, mais la capture de variables est exactement ce que je veux dans certaines macros.
Un langage vraiment bon devrait être à la fois propre et sale : conçu de manière propre, avec un petit noyau d'opérateurs bien compris et hautement orthogonaux, mais sale dans le sens où il laisse les hackers faire à leur guise. C est comme ça. Comme l'étaient les premiers Lisps. Un vrai langage de hacker aura toujours un caractère légèrement désinvolte.
Un bon langage de programmation devrait avoir des fonctionnalités qui font que le genre de personnes qui utilisent l'expression "génie logiciel" secouent la tête avec désapprobation. À l'autre extrémité du continuum se trouvent des langages comme Ada et Pascal, modèles de bienséance 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 vrais programmes, avec de vraies fonctionnalités et de vrais utilisateurs.
J'ai l'intuition que les meilleurs grands programmes commencent ainsi, plutôt que d'être conçus grands dès le départ, comme le barrage d'Hoover. C'est terrifiant de construire quelque chose de grand à partir de rien. Quand 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 avec un programme jetable et de continuer à l'améliorer. Cette approche est moins intimidante, et la conception du programme bénéficie de l'évolution. Je pense que, si on regardait, on découvrirait que c'est ainsi que 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é écrits en premier, 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 les 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 a non seulement été conçu pour écrire des programmes jetables, mais était à peu près un programme jetable lui-même. Perl a vu le jour comme une collection d'utilitaires pour générer des rapports, et n'a évolué en langage de programmation que lorsque les programmes jetables que les gens écrivaient en lui sont devenus plus importants. Ce n'est qu'à partir de Perl 5 (si c'est le cas) que le langage était adapté pour écrire des 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 qu'être installé, cependant. Un langage interactif, avec une interface en ligne de commande, est plus disponible que celui 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 concision. La concision 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, l'ultime en matière de concision est d'avoir le programme déjà écrit pour vous, et de simplement l'appeler. Et cela nous amène à ce qui, selon moi, sera une fonctionnalité 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 les chaînes de caractères. 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. De nombreux programmes Perl commencent probablement simplement par quelques appels de bibliothèque collés ensemble.
Je pense qu'une grande partie des progrès qui se produiront dans les langages de programmation au cours des cinquante prochaines années auront à voir avec les fonctions de bibliothèque. Je pense que les langages de programmation futurs auront des bibliothèques qui sont aussi soigneusement conçues que le langage de base. La conception des langages de programmation ne sera pas une question de savoir s'il faut rendre votre langage fortement ou faiblement typé, orienté objet, fonctionnel ou autre, mais de savoir comment concevoir de grandes bibliothèques. Le genre de concepteurs de langages qui aiment à réfléchir à la conception des systèmes de types peuvent frissonner à cette idée. C'est presque comme écrire des applications ! Tant pis. 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 volumineuses, il peut parfois prendre plus de temps de trouver la fonction dont vous avez besoin que de l'écrire 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ù le Common Lisp est en retard. Il n'y a que des bibliothèques rudimentaires pour manipuler les chaînes de caractères, et presque aucune pour communiquer avec le système d'exploitation. Pour des raisons historiques, le Common Lisp essaie de faire comme si le système d'exploitation n'existait pas. Et parce que vous ne pouvez pas communiquer avec le système d'exploitation, il est peu probable que vous puissiez écrire un programme sérieux en utilisant uniquement les opérateurs intégrés du Common Lisp. Vous devez également utiliser des astuces spécifiques à l'implémentation, et en pratique, celles-ci ne vous donnent pas tout ce que vous voulez. Les hackers auraient une bien meilleure opinion du Lisp si le Common Lisp disposait de puissantes bibliothèques de manipulation de chaînes de caractères et d'un bon support du système d'exploitation.
7 Syntaxe
Une langue avec la syntaxe du Lisp, ou plus précisément, le manque de syntaxe, pourrait-elle jamais devenir populaire ? Je ne connais pas la réponse à cette question. Je pense cependant que la syntaxe n'est pas la principale raison pour laquelle le Lisp n'est pas actuellement populaire. Le Common Lisp a des problèmes plus graves que la syntaxe inhabituelle. Je connais plusieurs programmeurs à l'aise avec la syntaxe préfixée et qui utilisent néanmoins Perl par défaut, car il dispose de puissantes bibliothèques de manipulation de chaînes de caractères et peut communiquer avec le système d'exploitation.
Il y a deux problèmes possibles avec la notation préfixée : qu'elle soit inhabituelle pour les programmeurs, et qu'elle ne soit pas assez dense. La sagesse conventionnelle dans le monde du Lisp est que le premier problème est le véritable. Je n'en suis pas si sûr. Oui, la notation préfixée fait paniquer les programmeurs ordinaires. Mais je ne pense pas que l'opinion des programmeurs ordinaires compte. Les langages deviennent populaires ou impopulaires en fonction de ce que pensent les hackers experts, et je pense que les hackers experts pourraient être en mesure de gérer la notation préfixée. La syntaxe de Perl peut être assez incompréhensible, mais cela n'a pas empêché la popularité de Perl. Cela a même pu contribuer à créer un culte de Perl.
Un problème plus sérieux est la diffusion de la notation préfixée. Pour les hackers experts, c'est vraiment un problème. Personne ne veut écrire (aref a x y) alors qu'ils pourraient écrire a[x,y].
Dans ce cas particulier, il existe un moyen de contourner le problème. Si nous traitons les structures de données comme si elles étaient des fonctions sur les 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 (ou rendre facultatifs) d'un grand nombre 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 en tenons à l'indentation. Traiter l'indentation comme significative éliminerait cette source courante de bogues et rendrait également 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é le Lisp tout au long de ma carrière de programmeur et je ne trouve toujours pas les expressions mathématiques préfixées naturelles. Et pourtant, c'est pratique, surtout lorsque vous générez du code, d'avoir des opérateurs qui prennent un nombre quelconque d'arguments. Donc si nous avons une syntaxe infixe, elle devrait probablement être implémentée sous forme de macro de lecture.
Je ne pense pas que nous devrions être religieusement opposés à l'introduction de syntaxe dans le Lisp, tant que cela se traduit de manière bien comprise en s-expressions sous-jacentes. Il y a déjà beaucoup de syntaxe dans le Lisp. Ce n'est pas nécessairement mauvais d'en introduire davantage, tant que personne n'est forcé de l'utiliser. En Common Lisp, certains délimiteurs sont réservés à la langue, ce qui suggère 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 manifestement non lisp dans le Common Lisp se trouve dans les chaînes de format ; format est un langage à part entière, et ce langage n'est pas le Lisp. S'il y avait un plan pour introduire plus de syntaxe dans le Lisp, les spécificateurs de format pourraient y être inclus. Ce serait une bonne chose si les macros pouvaient générer des spécificateurs de format de la même manière qu'elles génèrent tout autre type de code.
Un éminent hacker Lisp m'a dit que son exemplaire de CLTL s'ouvre sur la section format. Le mien aussi. Cela indique probablement qu'il y a de la place pour l'amélioration. Cela peut aussi signifier que les programmes font beaucoup d'E/S.
8 Efficacité
Une bonne langue, comme tout le monde le sait, doit 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 de la langue. Comme Knuth l'a fait remarquer il y a longtemps, la vitesse n'a d'importance que dans certains goulots d'étranglement critiques. Et comme de nombreux programmeurs l'ont observé depuis, on se trompe très souvent sur l'emplacement de ces goulots d'étranglement.
Donc, en pratique, le moyen d'obtenir du code rapide est d'avoir un très bon profileur, plutôt que, par exemple, de rendre la langue fortement typée. Vous n'avez pas besoin de connaître le type de chaque argument dans chaque appel du programme. Vous devez pouvoir déclarer les types d'arguments dans les goulots d'étranglement. Et surtout, vous devez pouvoir découvrir où se trouvent les goulots d'étranglement.
Une plainte que les gens ont eue avec le Lisp est qu'il est difficile de savoir 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 de toute façon, 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 la langue qu'un compilateur qui génère du code rapide. Ici, encore une fois, les concepteurs de langages sont quelque peu déconnectés de leurs utilisateurs. Ils font un travail vraiment bon pour résoudre légèrement le mauvais problème.
Il pourrait être une bonne idée d'avoir un profileur actif - de pousser les données de performance au programmeur au lieu d'attendre qu'il vienne les demander. Par exemple, l'éditeur pourrait afficher les goulots d'étranglement en rouge lorsque le programmeur modifie le code source. Une autre approche consisterait à représenter d'une manière ou d'une autre ce qui se passe dans les programmes en cours d'exécution. Ce serait un énorme avantage, en particulier dans les applications basées sur le serveur, 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 l'exécution d'un programme, ou même émettre des sons qui indiquent ce qui se passe.
Le son est un bon indice des problèmes. Dans un endroit où j'ai travaillé, nous avions un grand tableau de cadrans montrant ce qui se passait sur nos serveurs Web. Les aiguilles étaient déplacées par de petits servomoteurs qui faisaient un léger bruit lorsqu'ils tournaient. Je ne pouvais pas voir le tableau depuis mon bureau, mais j'ai constaté que je pouvais dire immédiatement, au son, quand 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 motifs 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 d'envoyer le processeur dans de nombreuses fausses pistes, mais je n'ai jamais eu un bon moyen de voir ce qu'il fait.
Un certain nombre de Lisps se compilent maintenant en code octet, 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é intéressante du langage. Il pourrait être judicieux de faire du code octet une partie officielle du langage et de permettre aux programmeurs d'utiliser du code octet en ligne dans les goulots d'étranglement. Alors ces optimisations seraient également portables.
La nature de la vitesse, telle que perçue par l'utilisateur final, peut changer. Avec l'essor des applications basées sur le serveur, de plus en plus de programmes peuvent s'avérer limités par les entrées/sorties. Il vaudra la peine de rendre les entrées/sorties rapides. Le langage peut aider avec des mesures simples et directes comme des fonctions de sortie formatée simples et rapides, et aussi avec des changements structurels profonds comme la mise en cache et les objets persistants.
Les utilisateurs s'intéressent au temps de réponse. Mais une autre forme d'efficacité sera de plus en plus importante : le nombre d'utilisateurs simultanés que vous pouvez prendre en charge par processeur. Bon nombre des applications intéressantes écrites dans un avenir proche seront basées sur le serveur, et le nombre d'utilisateurs par serveur est la question cruciale pour quiconque héberge de telles applications. Dans le coût en capital d'une entreprise offrant une application basée sur le 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 aurait un processeur de plus en plus puissant sur son bureau. Et selon la loi de Parkinson, les logiciels se sont développés pour utiliser les ressources disponibles. Cela changera avec les applications basées sur le serveur. Dans ce monde, le matériel et le logiciel seront fournis ensemble. Pour les entreprises qui proposent des applications basées sur le serveur, le nombre d'utilisateurs qu'elles peuvent prendre en charge par serveur fera une très grande différence sur leurs bénéfices.
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 nécessaire 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 c'est le cas pour de nombreux langages de programmation. Donc la plupart des hackers attendront probablement quelques années avant même d'envisager de l'utiliser.
Les inventeurs de nouvelles choses merveilleuses sont souvent surpris de découvrir cela, mais il faut du temps pour faire passer n'importe quel message aux gens. Un ami à moi fait rarement quelque chose la première fois qu'on lui demande. Il sait que les gens demandent parfois des choses dont ils finissent par ne plus vouloir. Pour éviter de perdre son temps, il attend jusqu'à la troisième ou quatrième fois qu'on lui demande de faire quelque chose ; à ce moment-là, celui qui lui demande est peut-être assez agacé, mais au moins il veut probablement vraiment ce qu'il demande.
La plupart des gens ont appris à faire un filtrage similaire sur les nouvelles choses qu'ils entendent. Ils ne commencent même pas à y prêter attention tant qu'ils n'en ont pas entendu parler une dizaine de fois. Ils sont parfaitement justifiés : la majorité des nouvelles tendances se révèlent être une perte de temps et finissent par disparaître. En retardant l'apprentissage du 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 ne commencent à le comprendre. Nous avons écrit ce qui était, à ma connaissance, 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 ignoraient simplement.
La bonne nouvelle, c'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 les gens finiront par l'entendre. Ce n'est pas quand les gens remarquent que vous êtes là qu'ils vous prêtent attention ; c'est quand ils remarquent que vous êtes toujours là.
C'est tout aussi bien que cela prenne 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 par un petit nombre d'utilisateurs précoces. Les utilisateurs précoces sont sophistiqués et exigeants, et ils éliminent rapidement les défauts restants dans votre technologie. Quand vous n'avez que quelques utilisateurs, vous pouvez être en contact étroit avec tous. Et les utilisateurs précoces sont indulgents lorsque vous améliorez votre système, même si cela entraîne quelques ruptures.
Il y a deux façons dont les nouvelles technologies sont introduites : la méthode de croissance organique et la méthode du grand bang. La méthode de croissance organique est exemplifiée par la classique start-up de garage sous-financée. Deux gars, travaillant dans l'obscurité, développent une nouvelle technologie. Ils la lancent sans marketing et n'ont initialement que quelques utilisateurs (passionnément dévoués). Ils continuent à améliorer la technologie, et pendant ce temps leur base d'utilisateurs augmente par bouche-à-oreille. Avant de le savoir, ils sont devenus importants.
L'autre approche, la méthode du grand bang, est exemplifiée par la start-up financée par des capital-risqueurs et fortement commercialisée. 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.
Généralement, les gars du garage envient les gars du grand bang. Les gars du grand bang sont lisses et confiants, et respectés par les capital-risqueurs. Ils peuvent se permettre le meilleur de tout, et la campagne de relations publiques entourant le lancement a pour effet secondaire d'en faire des célébrités. Les gars de la croissance organique, assis dans leur garage, se sentent pauvres et peu aimés. Et pourtant, je pense qu'ils ont souvent tort de se plaindre. La croissance organique semble produire de meilleures technologies et des fondateurs plus riches que la méthode du grand bang. Si vous regardez les technologies dominantes d'aujourd'hui, vous constaterez que la plupart d'entre elles ont grandi de manière organique.
Ce modèle ne s'applique pas seulement aux entreprises. On le voit aussi dans la recherche parrainée. Multics et Common Lisp étaient des projets de grand bang, et Unix et MacLisp étaient des projets de croissance organique.
10 Redesign
"Le meilleur écrit est le réécrit", a écrit E. B. White. Tout bon écrivain le sait, et c'est vrai pour les logiciels aussi. La partie la plus importante de la conception est la reconception. Les langages de programmation, en particulier, ne sont pas assez redessinés.
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 dans ses capacités et, en même temps, du scepticisme du vétéran. Vous devez être capable de penser how hard can it be? avec une moitié de votre cerveau tout en pensant it will never work avec l'autre.
Le truc, c'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 sur la possibilité de résoudre le problème, mais sceptique sur la valeur de la solution que vous avez jusqu'à présent.
Les gens qui font un bon travail pensent souvent que ce sur quoi ils travaillent n'est pas bon. Les autres voient ce qu'ils ont fait et sont remplis 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 équilibrés, ils feront avancer un projet de la même manière que vos deux jambes font avancer un vélo. Dans la première phase du moteur d'innovation à deux temps, vous travaillez avec acharnement sur un problème, inspiré par votre confiance dans votre capacité à le résoudre. Dans la deuxième phase, vous regardez ce que vous avez fait à la lumière crue 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 en mesure de regarder votre système certes incomplet et de penser, "how hard can it be to get the rest of the way?", poursuivant ainsi le cycle.
Il est délicat de garder les deux forces équilibrées. 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 redesign est bon. La prose peut être réécrite encore et encore jusqu'à ce que vous soyez satisfait. Mais le logiciel, en règle générale, n'est pas assez redesigné. La prose a des lecteurs, mais le logiciel a des utilisateurs. Si un écrivain réécrit un essai, les gens qui ont lu l'ancienne version ne se plaindront probablement pas que leurs pensées aient été brisées par une incompatibilité nouvellement introduite.
Les utilisateurs sont un double tranchant. Ils peuvent vous aider à améliorer votre langage, mais ils peuvent aussi vous dissuader de l'améliorer. Choisissez donc vos utilisateurs avec soin et soyez lent à en augmenter le 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 changer plus que vous ne le pensez. Introduire des changements est comme arracher un pansement : la douleur est un souvenir presque aussitôt que vous la ressentez.
Tout le monde sait que ce n'est pas une bonne idée d'avoir un langage conçu par un comité. Les comités produisent une mauvaise conception. Mais je pense que le pire danger des comités est qu'ils interfèrent avec le redesign. C'est tellement de travail d'introduire des changements que personne ne veut se donner la peine. Quoi qu'un comité décide, cela tend à rester ainsi, même si la plupart des membres n'en sont pas satisfaits.
Même un comité de deux personnes fait obstacle au redesign. Cela se produit particulièrement dans les interfaces entre les morceaux de logiciel écrits par deux personnes différentes. Pour changer l'interface, les deux doivent accepter 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 improvisées 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 des strates d'abstraction empilées verticalement. Alors l'interface aura tendance à être possédée par l'un d'entre eux. Le niveau inférieur de deux niveaux sera soit un langage dans lequel le niveau supérieur est écrit, auquel cas le niveau inférieur possédera l'interface, soit 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 nous sommes peut-être trompés en pensant que les hackers sont rebutés par la bizarrerie de Lisp. Cette illusion réconfortante a peut-être empêché de voir le vrai problème avec Lisp, ou du moins avec Common Lisp, qui est qu'il est nul pour faire ce que les hackers veulent faire. Le langage d'un hacker a besoin de puissantes bibliothèques et de quelque chose à hacker. Common Lisp n'a ni l'un ni l'autre. Le langage d'un hacker est concis et hackable. Common Lisp ne l'est pas.
La bonne nouvelle, c'est que ce n'est pas Lisp qui est nul, mais Common Lisp. Si nous pouvons développer un nouveau Lisp qui soit un véritable langage de hacker, je pense que les hackers l'utiliseront. Ils utiliseront n'importe quel langage qui fera le travail. Tout ce que nous avons à faire est de nous assurer que ce nouveau Lisp fait mieux que les autres langages pour un travail important.
L'histoire offre un certain encouragement. Au fil du temps, les nouveaux langages de programmation successifs ont pris de plus en plus de fonctionnalités à 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 pas de macros. Un nouveau Lisp serait une étape naturelle dans cette progression.
Je pense parfois qu'un bon coup de marketing serait de l'appeler une version améliorée de Python. Cela semble plus tendance 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 pense 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 le 6.001 et l'ont compris, par exemple. Et ce sont les utilisateurs dont vous avez besoin pour 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 quand 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 pas beaucoup Lisp lui-même.
Si je ne connaissais pas Lisp, la lecture de cela me poserait des questions. Un langage qui me rendrait un meilleur programmeur, si cela veut dire 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 assez réceptifs à un nouveau Lisp, même s'il est appelé 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.
Dans le domaine des bibliothèques, je pense qu'il est possible de surpasser des langages comme Perl et Python à leur propre jeu. Un grand nombre des nouvelles applications qui devront être écrites dans les années à venir seront des applications côté serveur. Il n'y a aucune raison pour qu'un nouveau Lisp n'ait pas des bibliothèques de chaînes de caractères aussi bonnes que Perl, et si ce nouveau Lisp avait également de puissantes bibliothèques pour les applications côté serveur, 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.
Ce serait même une victoire encore plus grande d'avoir un support de langage de base pour les applications côté serveur. Par exemple, un support explicite pour les programmes avec plusieurs utilisateurs, ou la propriété des données au niveau des étiquettes de type.
Les applications côté serveur nous donnent également la réponse à la question de ce à quoi ce nouveau Lisp sera utilisé pour hacker. Cela ne nuirait pas 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 serait préférable de suivre le modèle de Tcl, et de fournir le Lisp avec un système complet pour prendre en charge les applications côté serveur. Lisp est un bon choix pour les applications côté serveur. Les fermetures lexicales offrent un moyen d'obtenir l'effet de 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 faut de meilleurs outils pour écrire des applications côté serveur, et il faut 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 environnement 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 de 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 voulez optimiser, il y a un profileur vraiment bon qui vous indique où concentrer votre attention. Vous pouvez rendre les boucles internes aveuglantes, même en écrivant du bytecode en ligne si nécessaire.
Il y a beaucoup de bons exemples à apprendre, et le langage est assez intuitif pour que vous puissiez apprendre à l'utiliser à partir d'exemples en quelques minutes. Vous n'avez pas besoin de consulter le manuel souvent. Le manuel est mince et comporte peu d'avertissements et de réserves.
Le langage a un noyau réduit et des bibliothèques puissantes et hautement orthogonales qui sont aussi soigneusement conçues que le langage de base. Les bibliothèques fonctionnent bien ensemble ; tout dans le langage s'emboîte comme les pièces d'un bel appareil photo. Rien n'est obsolète ou conservé pour des raisons de compatibilité. Le code source de toutes les bibliothèques est facilement accessible. Il est facile de communiquer avec le système d'exploitation et avec les applications écrites dans d'autres langages.
Le langage est construit par couches. Les abstractions de haut niveau sont construites de manière très transparente à partir d'abstractions de niveau inférieur, que vous pouvez atteindre si vous le souhaitez.
Rien ne vous est caché qui ne doit absolument pas l'être. Le langage n'offre des abstractions que comme un moyen de vous épargner du travail, plutôt que comme un moyen de vous dire quoi faire. En fait, le langage vous encourage à être un participant égal à sa conception. Vous pouvez tout changer à ce sujet, 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] Les 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, initialement, étaient des moyens d'éviter la capture de variables et l'évaluation multiple ; les exemples de Hart sont sujets aux deux.
[2] Dans When the Air Hits Your Brain, le neurochirurgien Frank Vertosick raconte une conversation dans laquelle son résident en chef, Gary, parle de la différence entre les chirurgiens et les internistes ("puces") :
Gary et moi avons commandé une grande pizza et avons trouvé un box ouvert. Le chef a allumé une cigarette. "Regardez ces putains de puces, à bavarder sur une maladie qu'ils verront une fois dans leur vie. C'est le problème avec les puces, ils n'aiment que les trucs bizarres. Ils détestent leurs cas de pain et de beurre. C'est la différence entre nous et les putains de puces. Voyez, on adore les grosses hernies discales lombaires juteuses, mais eux détestent l'hypertension..."
Il est difficile de penser à une hernie discale lombaire comme juteuse (sauf littéralement). Et pourtant, je pense que je sais 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. Bien sûr, il vaut mieux que tout fonctionne simplement. Et pourtant, il y a indéniablement une satisfaction sombre à traquer certains types de bugs.