Loading...

ÊTRE POPULAIRE

Original

Mai 2001

(Cet article a été écrit comme une sorte de business plan 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 de mes amis a dit un jour à un éminent expert en systèmes d'exploitation qu'il voulait concevoir un langage de programmation vraiment performant. L'expert lui a répondu 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 que, quelle que soit la qualité de son langage, personne ne l'utiliserait. Du moins, c'est ce qui est arrivé au langage qu'il avait conçu.

Qu'est-ce qui fait qu'un langage est populaire ? Les langages populaires méritent-ils leur popularité ? Est-il utile de définir un bon langage de programmation ? Comment procéderiez-vous ?

Je pense que les réponses à ces questions peuvent être trouvées en observant les hackers et en découvrant 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, par exemple, un exercice de sémantique dénotationnelle ou de conception de compilateur) si et seulement si les hackers l'apprécient.

1 La mécanique de la popularité

Il est vrai que la plupart des gens ne choisissent pas un langage de programmation uniquement en fonction de ses qualités. La plupart des programmeurs se font dire quel langage 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 important qu'on le pense parfois. Je pense qu'un problème plus important est que l'idée que se fait un hacker d'un bon langage de programmation n'est pas la même que celle que se font la plupart des concepteurs de langages.

Entre les deux, c'est l'avis 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 aux faiblesses humaines, tout comme les chaussures doivent être conçues pour les pieds humains. Si une chaussure vous serre lorsque vous la mettez, c'est qu'elle est mauvaise, aussi élégante soit-elle en tant qu'œuvre d'art.

Il se peut que la majorité des programmeurs ne sache pas distinguer un bon langage d'un mauvais. Mais c'est pareil avec n'importe quel autre outil. Cela ne veut pas dire que c'est une perte de temps d'essayer de concevoir un bon langage. Les hackers experts savent reconnaître un bon langage lorsqu'ils en voient un, et ils l'utiliseront. Les hackers experts sont une toute petite minorité, il faut l'admettre, mais cette toute petite minorité écrit tous les bons logiciels, et leur influence est telle que le reste des programmeurs aura tendance à utiliser le langage qu'ils utilisent. Souvent, en effet, il ne s'agit pas seulement d'influence mais de commandement : souvent, les hackers experts sont les mêmes personnes qui, en tant que patrons ou conseillers pédagogiques, disent aux autres programmeurs quel langage utiliser.

L’opinion des experts en hacking n’est pas la seule force qui détermine la popularité relative des langages de programmation – les logiciels traditionnels (Cobol) et le battage médiatique (Ada, Java) jouent également un rôle – mais je pense que c’est la force la plus puissante sur le long terme. Avec 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’expérience des utilisateurs réels conduisent toujours à des améliorations. Regardez à quel point n’importe quel langage populaire a changé au cours de son existence. 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 ont passé quelques années à utiliser Lisp pour écrire de vrais programmes. [1]

Qu'un langage doive être bon ou non pour être populaire, je pense qu'il doit être populaire pour être bon. Et il doit rester populaire pour rester bon. L'état de l'art des langages de programmation n'est pas figé. Et pourtant, les Lisp 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 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 peuvent-ils en entendre parler ? Par d'autres hackers. Mais il faut qu'un groupe initial de hackers utilise le langage pour que d'autres en entendent parler. Je me demande quelle doit être la taille de ce groupe ; 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 décident de leur propre chef de l'utiliser, je le considérerais comme réel.

Il ne faut pas s'étonner qu'il soit plus difficile de passer de zéro à vingt que de vingt à mille. La meilleure façon d'obtenir ces vingt premiers utilisateurs est probablement d'utiliser un cheval de Troie : donner aux gens l'application qu'ils souhaitent, 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 d'Unix, et plus tard, Perl l'était 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 très populaire car il n'est pas le langage de script d'un système très populaire. La popularité qu'il conserve remonte aux années 1960 et 1970, lorsqu'il était le langage de script du MIT. De nombreux grands programmeurs de l'époque ont été associés au MIT à un moment donné. Et au début des années 1970, avant le C, le dialecte Lisp du MIT, appelé MacLisp, était l'un des seuls langages de programmation qu'un hacker sérieux pouvait vouloir utiliser.

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

Les langages de programmation n'existent pas de manière isolée. Pirater est un verbe transitif (les pirates informatiques piratent généralement quelque chose) et, dans la pratique, les langages sont jugés en fonction de ce qu'ils sont censés pirater. 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 orphelin. Il était à l'origine doté d'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. Common Lisp aurait pu rester populaire s'il avait été un bon langage de script pour Unix. Il est, hélas, 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 façon de voir les choses est qu'un langage de programmation n'est pas vraiment un langage de programmation à moins qu'il ne soit aussi le langage de script de quelque chose. Cela ne semble injuste que si cela arrive par surprise. Je pense que ce n'est pas plus injuste que d'attendre d'un langage de programmation qu'il ait, par exemple, une implémentation. Cela fait simplement 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 des logiciels, mais les hackers individuels ne le feront pas, et c'est eux qu'il faut attirer.

Un langage doit aussi avoir un livre sur lui. Le livre doit être concis, bien écrit et plein 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 de l'importance pour les hackers.

Il faudrait aussi 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 déjà démodés. Leur format est pratique et la censure de fait 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 apprendre de nouvelles langues.

3. Concision

Étant donné que vous pouvez fournir les trois choses dont tout langage a besoin (une implémentation gratuite, un livre et quelque chose à pirater), comment créer un langage qui plaira aux hackers ?

Les hackers aiment la concision. Ils sont paresseux, tout comme les mathématiciens et les architectes modernistes : ils détestent tout ce qui est superflu. Il ne serait pas très loin de la vérité de dire qu'un hacker qui s'apprête à écrire un programme décide du langage à utiliser, du moins inconsciemment, en fonction du nombre total de caractères qu'il devra saisir. Si ce n'est pas exactement 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 dorloter l'utilisateur avec des expressions longues et verbeuses qui sont censées ressembler à de l'anglais. Cobol est connu pour cette faille. Un pirate informatique envisagerait de lui demander 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.

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 pendant 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 saisie en plus. Et ils ont également des longueurs différentes, ce qui signifie que les arguments ne s'alignent pas lorsqu'ils sont appelés, comme le font souvent car et cdr, sur des lignes successives. J'ai découvert que la façon dont le code s'aligne sur la page est très importante. Je peux à peine lire du code Lisp lorsqu'il est défini dans une police à largeur variable, et des amis disent que c'est également vrai pour d'autres langages.

La concision est un point sur lequel les langages fortement typés perdent. Toutes choses étant égales par ailleurs, personne ne veut commencer un programme avec un tas de déclarations. Tout ce qui peut être implicite doit l'être.

Les noms individuels doivent é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 Common Lisp intégrés sont comiquement longs. Les concepteurs de Common Lisp s'attendaient probablement à ce que les utilisateurs disposent d'éditeurs de texte capables de saisir ces noms longs à leur place. Mais le coût d'un nom long ne se limite pas au coût de sa saisie. Il y a aussi le coût de sa 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 concision pour un hacker : pouvoir faire ce qu'il veut. Dans l'histoire des langages de programmation, un nombre surprenant d'efforts ont été déployés pour 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 que le programmeur va devoir faire ? Je pense que les concepteurs de langage feraient mieux de considérer leur utilisateur cible comme un génie qui devra faire des choses qu'il n'a jamais prévues, plutôt que comme un maladroit qui a besoin d'être protégé de lui-même. Le maladroit se tirera une balle dans le pied de toute façon. Vous pouvez l'empêcher de faire référence à des variables dans un autre package, mais vous ne pouvez pas l'empêcher d'écrire un programme mal conçu pour résoudre le mauvais problème et de prendre une éternité à le faire.

Les bons programmeurs veulent souvent faire des choses dangereuses et peu recommandables. Par peu recommandables, j'entends des choses qui se cachent derrière la façade sémantique que le langage essaie de présenter : par exemple, s'emparer de la représentation interne d'une abstraction de haut niveau. Les hackers aiment pirater, et pirater signifie s'introduire dans les choses et deviner le concepteur original.

Laissez-vous influencer. Lorsque vous créez un outil, les gens l'utilisent d'une manière que vous n'aviez pas prévue, et c'est particulièrement vrai pour un outil très articulé comme un langage de programmation. De nombreux hackers voudront modifier votre modèle sémantique d'une manière que vous n'auriez jamais imaginée. Je dis, laissez-les faire ; donnez au programmeur 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 parcourir les champs d'une structure — pour éliminer les références à un objet supprimé, par exemple, ou trouver des champs non 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 puisse appeler sur n'importe quelle structure. Je ne peux accéder aux champs que par leur nom, car c'est ce qu'une structure est censée signifier.

Un hacker ne voudra peut-être qu'une ou deux fois modifier le modèle de fonctionnement prévu dans un programme de grande envergure. Mais quelle différence cela fait-il d'en être capable. Et il peut s'agir de bien plus que de résoudre un problème. Il y a là aussi une forme de plaisir. Les hackers partagent le plaisir secret du chirurgien à fouiller dans les entrailles dégoûtantes, le plaisir secret de l'adolescent à faire éclater 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 macabres. Ils connaissent leur public.

Historiquement, Lisp a toujours su laisser les hackers faire ce qu'ils voulaient. Le politiquement correct de Common Lisp est une aberration. Les premiers Lisp vous permettaient de tout avoir sous la main. Une bonne partie de cet esprit est heureusement préservée dans les macros. Quelle merveille 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 très 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 la macro. Les macros hygiéniques incarnent le principe opposé. Elles essaient de vous empêcher de comprendre ce qu'elles font. Je n'ai jamais entendu les macros hygiéniques expliquées en une seule 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 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 doit être à la fois propre et sale : bien 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. C'était aussi le cas des premiers Lisp. Un vrai langage de hacker aura toujours un caractère légèrement rafleur.

Un bon langage de programmation doit avoir des caractéristiques qui font que les personnes qui utilisent l'expression « ingénierie logicielle » hochent la tête d'un air désapprobateur. À l'autre extrémité du continuum se trouvent des langages comme Ada et Pascal, des modèles de propriété 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 adapté à l'écriture des types de programmes qu'ils souhaitent écrire. Et cela signifie, peut-être de manière surprenante, qu'il doit être adapté à l'écriture de 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. Ce qui est surprenant avec les programmes jetables, c'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 vers de vrais programmes, avec de vraies fonctionnalités et de vrais utilisateurs.

J'ai l'impression que les meilleurs grands programmes commencent ainsi, plutôt que d'être conçus en grand dès le départ, comme le barrage Hoover. Il est terrifiant de construire quelque chose de grand à partir de rien. Lorsque les gens s'attaquent à un projet trop grand, ils se sentent dépassés. Soit le projet s'enlise, soit le résultat est stérile et bancal : un centre commercial plutôt qu'un vrai centre-ville, Brasilia plutôt que Rome, Ada plutôt que C.

Une autre façon de concevoir un gros programme est de commencer avec un programme jetable et de l'améliorer continuellement. Cette approche est moins intimidante et la conception du programme bénéficie de l'évolution. Je pense que si l'on y réfléchit bien, la plupart des gros programmes se développeraient de cette façon. Et ceux qui ont évolué de cette façon sont probablement toujours écrits dans le langage dans lequel ils ont été écrits à l'origine, 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 soit utilisé pour les gros systèmes, vous devez le rendre adapté à l'écriture de programmes jetables, car c'est de là que viennent les gros 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 lui-même un programme jetable. Perl a commencé sa vie comme une collection d'utilitaires pour générer des rapports, et n'a évolué vers un langage de programmation qu'à mesure que le nombre de programmes jetables écrits en son sein a augmenté. Ce n'est qu'à partir de Perl 5 (si c'était le cas) que le langage est devenu adapté à l'écriture de programmes sérieux, et pourtant il était déjà très populaire.

Qu'est-ce qui fait qu'un langage est bon pour les programmes jetables ? Pour commencer, il doit être facilement disponible. Un programme jetable est quelque chose que vous prévoyez d'écrire en une heure. Le langage doit donc probablement déjà être installé sur l'ordinateur que vous utilisez. Il ne peut pas s'agir de quelque chose que vous devez installer avant de l'utiliser. Il doit être là. C était là parce qu'il était fourni 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 toutefois bien plus que simplement être installé. Un langage interactif, doté d'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 doit être interactif et démarrer rapidement.

Un autre élément que vous recherchez dans un programme jetable est la concision. La concision est toujours attrayante pour les hackers, et plus encore dans un programme qu'ils espèrent produire en une heure.

6 bibliothèques

Bien sûr, le summum de la 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, deviendra une fonctionnalité de plus en plus importante des langages de programmation : les fonctions de bibliothèque. Perl gagne parce qu'il dispose 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 écrits à l'origine pour convertir ou extraire des données. De nombreux programmes Perl commencent probablement par quelques appels de bibliothèque collés ensemble.

Je pense que les avancées qui se produiront dans les langages de programmation au cours des cinquante prochaines années seront en grande partie liées aux fonctions de bibliothèque. Je pense que les langages de programmation du futur auront des bibliothèques aussi soigneusement conçues que le langage de base. La conception d'un langage de programmation ne se résumera pas à savoir s'il faut le rendre fortement ou faiblement typé, ou orienté objet, ou fonctionnel, ou quoi que ce soit d'autre, mais à la façon de concevoir de bonnes bibliothèques. Le genre de concepteurs de langages qui aiment réfléchir à la façon de concevoir des systèmes de typage risquent de frémir à cette idée. C'est presque comme écrire des applications ! Dommage. Les langages sont faits pour les programmeurs, et les bibliothèques sont ce dont les programmeurs ont besoin.

Il est difficile de concevoir de bonnes bibliothèques. Il ne s'agit pas simplement d'écrire beaucoup de code. Une fois que les bibliothèques deviennent trop grandes, il peut parfois falloir plus de temps pour trouver la fonction dont vous avez besoin que pour écrire le code vous-même. Les bibliothèques doivent être conçues à l'aide d'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 dans lequel Common Lisp n'est pas à la hauteur. Il n'existe 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, Common Lisp essaie de faire comme si le système d'exploitation n'existait pas. Et comme 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 de Common Lisp. Vous devez également utiliser des hacks spécifiques à l'implémentation, et en pratique, ceux-ci ont tendance à ne pas vous donner tout ce que vous voulez. Les hackers auraient une bien meilleure opinion de Lisp si Common Lisp avait de puissantes bibliothèques de chaînes de caractères et un bon support du système d'exploitation.

7 Syntaxe

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

Il y a deux problèmes possibles avec la notation préfixe : elle est peu familière aux programmeurs et elle n'est pas assez dense. L'opinion commune dans le monde de Lisp est que le premier problème est le vrai. Je n'en suis pas si sûr. Oui, la notation préfixe fait paniquer les programmeurs ordinaires. Mais je ne pense pas que l'opinion des programmeurs ordinaires importe. Les langages deviennent populaires ou impopulaires en fonction de ce que les hackers experts pensent d'eux et je pense que les hackers experts devraient être capables de gérer la notation préfixe. La syntaxe de Perl peut être assez incompréhensible, mais cela n'a pas empêché la popularité de Perl. Au contraire, cela a peut-être contribué à nourrir un culte de Perl.

Un problème plus sérieux est la diffusion de la notation des préfixes. Pour les hackers experts, c'est vraiment un problème. Personne ne veut écrire (aref axy) alors qu'il pourrait é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 s'il s'agissait de fonctions sur des index, nous pourrions écrire (axy) à 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 facultative) de nombreuses 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 basons sur l'indentation. Traiter l'indentation comme significative éliminerait cette source courante de bugs et rendrait 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éfixées 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 sous la forme d'une sorte de macro de lecture.

Je ne pense pas que nous devrions être religieusement opposés à l'introduction d'une syntaxe dans Lisp, tant qu'elle se traduit de manière bien comprise dans les expressions-s sous-jacentes. Il existe déjà une bonne quantité de syntaxe dans Lisp. Ce n'est pas nécessairement une mauvaise chose d'en introduire davantage, tant que personne n'est obligé de l'utiliser. Dans Common Lisp, certains délimiteurs sont réservés au langage, 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 flagrants de Common Lisp se trouve dans les chaînes de formatage ; le formatage est un langage à part entière, et ce langage n'est pas Lisp. S'il existait un plan pour introduire davantage de syntaxe dans Lisp, les spécificateurs de format pourraient y être inclus. Ce serait une bonne chose que les macros puissent générer des spécificateurs de formatage de la même manière qu'elles génèrent n'importe quel autre type de code.

Un éminent hacker Lisp m'a dit que sa copie de CLTL était ouverte au format section. La mienne aussi. Cela indique probablement une marge d'amélioration. Cela peut également signifier que les programmes effectuent beaucoup d'E/S.

8 Efficacité

Comme chacun le sait, un bon langage doit générer du code rapide. Mais en pratique, je ne pense pas que la rapidité du code soit principalement due à des choses que vous faites lors de la conception du langage. Comme Knuth l'a souligné 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.

En pratique, le moyen d'obtenir un code rapide est d'avoir un très bon profileur, plutôt que, par exemple, de rendre le langage fortement typé. Vous n'avez pas besoin de connaître le type de chaque argument dans chaque appel du programme. Vous devez être capable de déclarer les types d'arguments dans les goulots d'étranglement. Et plus encore, vous devez être capable de trouver où se trouvent les goulots d'étranglement.

L'une des critiques que l'on peut faire à propos de Lisp est qu'il est difficile de déterminer ce qui est cher. C'est peut-être vrai. Cela peut aussi être inévitable si vous voulez avoir un langage très abstrait. Et dans tous les cas, je pense qu'un bon profilage contribuerait grandement à résoudre le problème : vous saurez rapidement ce qui est cher.

Une partie du problème est ici d'ordre social. 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 module complémentaire, 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 du très bon travail en résolvant légèrement le mauvais problème.

Il peut être judicieux d'avoir un profileur actif, pour transmettre les données de performances 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. Cela constituerait un avantage particulièrement important dans les applications basées sur un serveur, où vous devez examiner de nombreux programmes en cours d'exécution. Un profileur actif pourrait afficher graphiquement ce qui se passe dans la mémoire pendant l'exécution d'un programme, ou même émettre des sons indiquant ce qui se passe.

Le son est un bon signal de problème. Dans un endroit où je travaillais, nous avions un grand tableau de cadrans indiquant 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 découvert que je pouvais immédiatement savoir, grâce au son, qu'il y avait un problème avec un serveur.

Il serait même possible d'écrire un profileur qui détecterait automatiquement les algorithmes inefficaces. Je ne serais pas surpris si certains schémas d'accès à la mémoire se révélaient être des signes certains de mauvais algorithmes. S'il y avait un petit gars qui courait dans l'ordinateur pour exécuter nos programmes, il aurait probablement une histoire longue et plaintive à raconter sur son travail en tant qu'employé du gouvernement fédéral. J'ai souvent le sentiment que je fais faire beaucoup de chasses au trésor au processeur, mais je n'ai jamais eu de bon moyen de voir ce qu'il fait.

Un certain nombre de LISPS se compilent désormais en byte code, qui est ensuite exécuté par un interpréteur. Cela est généralement fait pour rendre l'implémentation plus facile à porter, mais cela pourrait être une fonctionnalité utile du langage. Ce pourrait être une bonne idée de faire du byte code une partie officielle du langage et de permettre aux programmeurs d'utiliser du byte code en ligne dans les goulots d'étranglement. De telles optimisations seraient alors é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 serveur, de plus en plus de programmes pourraient se révéler être liés aux E/S. Il vaudra la peine de rendre les E/S rapides. Le langage peut aider à des mesures simples comme des fonctions de sortie simples, rapides et formatées, ainsi qu'à des changements structurels profonds comme la mise en cache et les objets persistants.

Les utilisateurs s'intéressent au temps de réponse. Mais un autre type d'efficacité va prendre de plus en plus d'importance : le nombre d'utilisateurs simultanés que vous pouvez prendre en charge par processeur. De nombreuses applications intéressantes écrites dans un avenir proche seront basées sur un serveur, et le nombre d'utilisateurs par serveur est la question cruciale pour quiconque héberge de telles applications. Dans le coût d'investissement d'une entreprise proposant une application basée sur un serveur, c'est le facteur décisif.

Pendant des années, l'efficacité n'a pas vraiment 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 va changer avec les applications basées sur serveur. Dans ce monde, le matériel et les logiciels seront fournis ensemble. Pour les entreprises qui proposent des applications basées sur serveur, le nombre d'utilisateurs qu'elles peuvent prendre en charge par serveur fera une très grande différence sur le résultat net.

Dans certaines applications, le processeur sera le facteur limitant et la vitesse d'exécution sera l'élément le plus important à 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 des 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 différé.

9 Heure

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 de nombreux langages de programmation. La plupart des hackers auront donc tendance à attendre qu'un langage existe depuis quelques années avant même d'envisager de l'utiliser.

Les inventeurs de choses merveilleuses sont souvent surpris de découvrir cela, mais il faut du temps pour faire passer un message aux gens. Un de mes amis fait rarement quelque chose la première fois qu'on lui demande. Il sait que les gens demandent parfois des choses dont ils ne veulent pas. Pour éviter de perdre son temps, il attend la troisième ou la quatrième fois qu'on lui demande quelque chose ; à ce moment-là, celui qui lui demande 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 dont ils entendent parler. Ils ne commencent même pas à y prêter attention avant d'avoir entendu parler de quelque chose dix fois. Ils ont parfaitement raison : la majorité des nouveautés à la mode 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.

Ainsi, quiconque invente quelque chose de nouveau doit s'attendre à 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'il n'était pas nécessaire de la télécharger. Ce n'est pas qu'ils étaient stupides. Ils nous ont juste fait perdre notre temps.

La bonne nouvelle, c'est que la simple répétition résout le problème. Il vous suffit de continuer à raconter votre histoire et les gens finiront par vous entendre. Ce n'est pas quand les gens remarquent que vous êtes là qu'ils vous écoutent, mais quand ils remarquent que vous êtes toujours là.

Heureusement, il faut généralement un certain temps pour qu'une technologie prenne de l'ampleur. La plupart des technologies évoluent beaucoup même après leur lancement, en particulier les langages de programmation. Rien ne pourrait être plus bénéfique, pour une nouvelle technologie, que de n'être utilisée que quelques années par un petit nombre de pionniers. Les pionniers sont sophistiqués et exigeants, et éliminent rapidement les défauts restants de votre technologie. Lorsque vous n'avez que quelques utilisateurs, vous pouvez être en contact étroit avec eux tous. Et les pionniers sont indulgents lorsque vous améliorez votre système, même si cela entraîne des pannes.

Il existe deux façons d'introduire une nouvelle technologie : la méthode de la croissance organique et la méthode du big bang. La méthode de la croissance organique est illustrée par la start-up classique, qui se lance dans un garage sous-financé et qui se lance à l'improviste. Deux gars, travaillant dans l'ombre, développent une nouvelle technologie. Ils la lancent sans marketing et n'ont au départ que quelques utilisateurs (fanatiquement dévoués). Ils continuent d'améliorer la technologie et, entre-temps, leur base d'utilisateurs s'agrandit grâce au bouche-à-oreille. Avant même de s'en rendre compte, ils deviennent grands.

L’autre approche, la méthode du big bang, est illustrée par les startups financées par des investisseurs en capital-risque et fortement commercialisées. Elles se précipitent pour développer un produit, le lancent avec une grande publicité et, immédiatement (elles l’espèrent), ont une large base d’utilisateurs.

En général, les gars du garage envient les gars du big bang. Ces derniers sont calmes, sûrs d'eux et respectés par les capital-risqueurs. Ils peuvent s'offrir le meilleur de tout, et la campagne de relations publiques qui entoure le lancement a pour effet secondaire de les transformer en célébrités. Les gars de la croissance organique, assis dans leur garage, se sentent pauvres et mal aimés. Et pourtant, je pense qu'ils ont souvent tort de s'apitoyer sur leur sort. 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 connu une croissance organique.

Ce modèle ne s'applique pas seulement aux entreprises. On le retrouve également dans les recherches sponsorisées. Multics et Common Lisp étaient des projets de grande envergure, et Unix et MacLisp étaient des projets de croissance organique.

10 Refonte

« La meilleure écriture est la réécriture », a écrit EB White. Tout bon écrivain le sait, et c'est également vrai pour les logiciels. La partie la plus importante de la conception est la refonte. Les langages de programmation, en particulier, ne sont pas suffisamment repensés.

Pour écrire un bon logiciel, il faut avoir en tête deux idées opposées à la fois. Il faut avoir la foi naïve du jeune hacker en ses capacités, et en même temps le scepticisme du vétéran. Il faut être capable de penser à quel point cela peut être difficile avec une moitié de son cerveau tout en pensant que cela ne fonctionnera jamais avec l'autre.

L'astuce consiste à comprendre qu'il n'y a pas de réelle contradiction ici. Il faut être optimiste et sceptique à propos de deux choses différentes. Il faut être optimiste quant à la possibilité de résoudre le problème, mais sceptique quant à la valeur de la solution que vous avez trouvée jusqu'à présent.

Les gens qui font du bon travail pensent souvent que ce qu'ils font n'est pas bon. Les autres voient ce qu'ils ont fait et s'émerveillent, mais le créateur est plein d'inquiétude. Ce schéma n'est pas une coïncidence : c'est l'inquiétude qui a rendu le travail bon.

Si vous parvenez à équilibrer espoir et inquiétude, 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 cycles, vous travaillez furieusement 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 dans la froide lumière du matin et voyez très clairement tous ses défauts. Mais tant que votre esprit critique ne l'emporte pas sur votre espoir, vous serez capable d'examiner votre système, certes incomplet, et de vous demander à quel point il peut être difficile de faire le reste du chemin, perpétuant ainsi le cycle.

Il est difficile de maintenir l'équilibre entre ces deux forces. 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 hackers plus âgés, le scepticisme prédomine et ils n'osent même pas se lancer dans des projets ambitieux.

Tout ce que vous pouvez faire pour maintenir le cycle de refonte est une bonne chose. La prose peut être réécrite encore et encore jusqu'à ce que vous soyez satisfait. Mais les logiciels, en règle générale, ne sont pas suffisamment repensés. 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 ne se plaindront probablement pas que leurs pensées ont été brisées par une nouvelle incompatibilité.

Les utilisateurs sont une arme à double tranchant. Ils peuvent vous aider à améliorer votre langage, mais ils peuvent aussi vous dissuader de l’améliorer. Choisissez donc soigneusement vos utilisateurs et augmentez-les lentement. Avoir des utilisateurs, c’est comme optimiser : la meilleure solution est de la retarder. De plus, en règle générale, vous pouvez à tout moment vous permettre de changer plus que vous ne le pensez. Introduire un changement, c’est comme retirer un pansement : la douleur disparaît presque aussitôt que vous la ressentez.

Tout le monde sait que ce n'est pas une bonne idée de confier la conception d'un langage à un comité. Les comités produisent des conceptions médiocres. Mais je pense que le pire danger des comités est qu'ils interfèrent avec la refonte. Introduire des changements demande tellement de travail que personne ne veut s'en soucier. Quelle que soit la décision d'un comité, elle a tendance à rester telle quelle, même si la plupart des membres ne l'apprécient pas.

Même un comité de deux personnes peut faire obstacle à une refonte. Cela se produit notamment dans les interfaces entre des éléments de logiciel écrits par deux personnes différentes. Pour modifier l'interface, les deux personnes doivent accepter de la modifier en même temps. Les interfaces ont donc 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 pourrait être de concevoir des systèmes de manière à ce que les interfaces soient horizontales plutôt que verticales, de manière à ce que les modules soient toujours des strates d'abstraction empilées verticalement. L'interface aura alors tendance à appartenir à l'un d'entre eux. Le niveau inférieur des deux 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 avons peut-être fait une erreur en pensant que les hackers sont rebutés par l'étrangeté de Lisp. Cette illusion réconfortante nous a peut-être empêché de voir le vrai problème de Lisp, ou du moins de Common Lisp, qui est qu'il est nul pour faire ce que les hackers veulent faire. Un langage de hacker a besoin de bibliothèques puissantes et de quelque chose à pirater. 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, 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 fait le travail. Tout ce que nous avons à faire, c'est de nous assurer que ce nouveau Lisp fait un travail important mieux que les autres langages.

L'histoire nous offre quelques encouragements. Au fil du temps, les nouveaux langages de programmation successifs ont emprunté 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 une version édulcorée de Lisp avec une syntaxe infixe et sans macros. Un nouveau Lisp serait une étape naturelle dans cette progression.

Je pense parfois que ce serait une bonne stratégie marketing de l'appeler une version améliorée de Python. Cela semble 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 commençant par un L. Mais je pense que nous ne devrions pas avoir peur d'appeler le nouveau Lisp Lisp. Lisp jouit toujours d'un grand respect latent parmi les meilleurs hackers - ceux qui ont pris la 6.001 et l'ont comprise, par exemple. Et ce sont ces utilisateurs qu'il faut conquérir.

Dans « Comment devenir un hacker », Eric Raymond décrit Lisp comme une sorte de latin ou de 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 profonde d'illumination que vous vivrez lorsque vous l'aurez enfin compris ; cette expérience fera de vous un meilleur programmeur pour le reste de vos jours, même si vous n'utilisez jamais vraiment Lisp lui-même.

Si je ne connaissais pas Lisp, la lecture de ce texte m'amènerait à me poser des questions. Un langage qui ferait de moi un meilleur programmeur, si cela signifie quelque chose, signifie un langage qui serait meilleur pour la programmation. Et c'est en fait ce que sous-entend ce qu'Eric dit.

Tant que cette idée circule, je pense que les hackers seront assez réceptifs à un nouveau Lisp, même s'il s'appelle Lisp. Mais ce Lisp doit être un langage de hacker, comme les Lisp classiques des années 1970. Il doit être concis, simple et hackable. Et il doit disposer de bibliothèques puissantes 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 pour qu'un nouveau Lisp ne dispose pas de bibliothèques de chaînes aussi performantes que Perl, et si ce nouveau Lisp disposait également de bibliothèques puissantes pour les applications basées sur des serveurs, il pourrait être très populaire. Les vrais hackers ne lèveront pas le nez sur un nouvel outil qui leur permettra de résoudre des problèmes difficiles avec quelques appels de bibliothèque. N'oubliez pas que les hackers sont paresseux.

Il pourrait être encore plus avantageux de disposer d'un support de langage de base pour les applications basées sur serveur. 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 serveur nous donnent également la réponse à la question de savoir à quoi servira ce nouveau Lisp. Il ne serait pas inutile d'améliorer Lisp en tant que langage de script pour Unix. (Il serait difficile de le rendre pire.) Mais je pense qu'il y a des domaines dans lesquels les langages existants seraient plus faciles à battre. Je pense qu'il serait peut-être préférable de suivre le modèle de Tcl et de fournir le Lisp avec un système complet de prise en charge des applications basées sur serveur. Lisp est un choix naturel pour les applications basées sur serveur. Les fermetures lexicales permettent d'obtenir l'effet des sous-routines lorsque l'interface utilisateur n'est qu'une série de pages Web. Les expressions S se mappent bien sur le HTML et les macros sont efficaces pour le générer. Il faut de meilleurs outils pour écrire des applications basées sur serveur, et il faut un nouveau Lisp, et les deux fonctionneraient très bien ensemble.

12 Le langage des rêves

En guise de résumé, essayons de décrire le langage de rêve du hacker. Le langage de rêve est beau , propre et concis. Il possède 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 de tout programme que vous écrivez est du code spécifique à votre application. Tout le reste a été fait pour vous.

La syntaxe du langage est extrêmement concise. Vous n'aurez jamais besoin de taper un caractère inutile, ni même d'utiliser fréquemment la touche Maj.

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 existe un très bon profileur qui vous indique où concentrer votre attention. Vous pouvez créer des boucles internes à une vitesse fulgurante, voire écrire du byte code 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 consulter souvent le manuel. Le manuel est léger et comporte peu d'avertissements et de réserves.

Le langage possède un petit noyau et des bibliothèques puissantes et hautement orthogonales qui sont conçues avec autant de soin que le langage de base. Les bibliothèques fonctionnent toutes bien ensemble ; tout dans le langage s'assemble 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 communiquer avec le système d'exploitation et avec les 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 récupérer si vous le souhaitez.

Rien ne vous est caché qui ne doive absolument l'être. Le langage propose des abstractions uniquement pour vous épargner du travail, plutôt que pour vous dire quoi faire. En fait, le langage vous encourage à participer à sa conception à parts égales. Vous pouvez tout modifier, y compris sa syntaxe, et tout ce que vous écrivez a, autant que possible, le même statut que ce qui est prédéfini.

Remarques

[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'était 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 stand libre. Le chef a allumé une cigarette. « Regardez ces foutues puces, qui bavardent à propos d'une maladie qu'elles ne verront qu'une fois dans leur vie. C'est le problème avec les puces, elles n'aiment que les trucs bizarres. Elles détestent leur pain et leur beurre. C'est la différence entre nous et ces putains de puces. Voyez-vous, nous adorons les grosses hernies discales lombaires juteuses, mais elles détestent l'hypertension... »

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