LISP
Date d’apparition : 1958
- 1956 : pendant le Dartmouth Summer Research Project on Artificial Intelligence, John McCarthy réfléchit à un langage algébrique adapté au traitement de listes.
- 1958 : arrivé au MIT, McCarthy lance avec son équipe l’implémentation de Lisp sur l’IBM 704.
- 1960 : il publie Recursive Functions of Symbolic Expressions and Their Computation by Machine, l’article fondateur du langage.
- 1962 : le LISP 1.5 Programmer’s Manual donne une définition pratique du système et contribue à sa diffusion.
- Années 1960-1970 : plusieurs branches apparaissent, notamment Maclisp au MIT et Interlisp chez BBN puis Xerox PARC.
- 1974 : Richard Greenblatt décrit au MIT le projet d’une machine spécialement conçue pour exécuter Lisp.
- 1975 : Gerald Jay Sussman et Guy Steele présentent Scheme, un dialecte plus petit fondé sur une lecture renouvelée du calcul lambda.
- 1981-1984 : plusieurs communautés rapprochent leurs dialectes pour former Common Lisp, qui devient rapidement un standard de fait.
- 1994 : Common Lisp devient un standard ANSI.
- 2007 : Clojure montre que la famille Lisp peut encore être réinterprétée pour la JVM, la programmation fonctionnelle et la concurrence.
Donner une seule date de naissance reste donc un raccourci. Les idées commencent à se former en 1956, l’implémentation démarre en 1958 et la première publication scientifique paraît en 1960. Pour une fiche chronologique, 1958 reste la date la plus naturelle.
À quel besoin répond Lisp ?
Lors de la conférence de Dartmouth, McCarthy découvre notamment IPL, le langage utilisé par Allen Newell, Cliff Shaw et Herbert Simon pour leurs travaux sur Logic Theorist. IPL sait manipuler des listes, mais sa syntaxe reste très liée à la machine sur laquelle il fonctionne. McCarthy cherche une écriture plus proche des mathématiques et plus facile à composer.
Son propre projet d’intelligence artificielle, l’Advice Taker, renforce ce besoin. Pour faire raisonner un ordinateur, il faut représenter des phrases, des relations et des expressions logiques, puis les démonter, les comparer et en construire de nouvelles. Une simple suite de nombres convient mal à ce travail. Les listes imbriquées, en revanche, représentent naturellement des arbres et des expressions symboliques.
Lisp naît donc moins du besoin de calculer plus vite que de la nécessité de représenter et transformer des structures symboliques.
Pourquoi des listes ?
Une liste peut contenir des éléments simples, appelés historiquement des atomes, mais aussi d’autres listes. Elle permet ainsi de représenter une structure de profondeur quelconque :
(A (B C) (D (E F)))
Cette écriture peut être vue comme un arbre. Une branche peut elle-même contenir plusieurs branches, sans qu’il soit nécessaire de connaître à l’avance la taille de l’ensemble. Pour les chercheurs qui manipulent des formules, des démonstrations ou des phrases, cette souplesse est précieuse.
Le terme LISP vient de LISt Processor. Aujourd’hui, on écrit généralement Lisp lorsqu’on parle de la famille de langages, même si les documents historiques utilisent souvent les majuscules.
Pourquoi toutes ces parenthèses ?
Lisp utilise une notation préfixée : l’opération apparaît avant ses arguments. Une addition s’écrit par exemple :
(+ 2 3)
et l’expression mathématique (2 + 3) × 4 devient :
(* (+ 2 3) 4)
La première parenthèse ouvre une expression, le premier élément indique l’opération et les suivants sont ses arguments. Il n’est donc plus nécessaire de définir une priorité particulière entre +, * ou d’autres opérateurs : la structure de l’expression est visible directement.
John McCarthy avait pourtant imaginé une autre écriture, les M-expressions, plus proche de FORTRAN. Les listes parenthésées, appelées S-expressions, devaient surtout servir de représentation interne. L’arrivée de l’interpréteur rend les S-expressions directement utilisables pour programmer, et les M-expressions finissent par disparaître du projet. Les parenthèses qui devaient rester cachées deviennent ainsi l’une des syntaxes les plus reconnaissables de l’histoire de l’informatique.
CAR, CDR et CONS : des noms venus de l’IBM 704
Les premiers Lisp sont développés sur l’IBM 704, une machine à mots de 36 bits. Deux champs de 15 bits de certains mots sont directement accessibles par des instructions de la machine : la partie address et la partie decrement. Les premières cellules de liste utilisent précisément ces deux champs pour mémoriser deux adresses.
Cette organisation laisse trois noms célèbres dans le langage :
(car '(A B C)) ; donne A
(cdr '(A B C)) ; donne (B C)
(cons 'A '(B C)) ; construit (A B C)
CAR vient historiquement de Contents of the Address part of Register, CDR de Contents of the Decrement part of Register, tandis que CONS signifie simplement construct. Le matériel qui a accueilli le premier Lisp a donc laissé son vocabulaire dans des dialectes encore utilisés plusieurs décennies plus tard.
La récursion au cœur du langage
Durant l’été 1958, McCarthy travaille notamment sur la différentiation symbolique. Une expression mathématique possède naturellement une structure récursive : une somme contient des termes, qui peuvent eux-mêmes être des produits ou d’autres expressions. Il devient logique de définir une fonction capable de s’appeler elle-même pour descendre dans cette structure.
Un exemple moderne en Common Lisp montre bien le principe :
(defun somme (liste)
(if (null liste)
0
(+ (car liste)
(somme (cdr liste)))))
La fonction prend le premier élément avec car, puis recommence sur le reste de la liste avec cdr. Lorsqu’il ne reste plus rien, elle renvoie zéro.
McCarthy emprunte aussi la notation lambda aux travaux d’Alonzo Church. Une fonction peut alors être créée et manipulée comme une valeur. Cette association entre fonctions, récursion et structures de listes donne à Lisp un modèle de programmation très différent des langages impératifs dominants de l’époque.
Quand le programme devient une donnée
La caractéristique la plus originale de Lisp apparaît lorsque l’on compare ces deux expressions :
(+ 2 3)
'(+ 2 3)
La première demande l’addition et produit 5. L’apostrophe devant la seconde empêche son évaluation immédiate : Lisp considère alors (+ 2 3) comme une simple liste contenant trois éléments.
On peut donc construire, inspecter ou modifier cette liste comme n’importe quelle autre donnée, puis éventuellement demander son exécution :
(setq expression '(+ 2 3))
(eval expression)
eval renvoie ici 5. Cette proximité entre la représentation du programme et celle des données est souvent décrite par le terme homoiconicité. Elle permet notamment aux macros Lisp de recevoir du code sous forme de structure, de le transformer puis de produire un nouveau programme.
L’histoire réserve ici un épisode remarquable. McCarthy avait écrit eval comme une définition théorique destinée à son article. Steve Russell remarque que cette définition peut servir directement d’interpréteur, la traduit à la main en code machine et donne ainsi au système un interpréteur Lisp opérationnel. Une construction pensée pour expliquer le langage devient l’un de ses mécanismes pratiques.
La mémoire se libère toute seule
Les programmes Lisp construisent continuellement de nouvelles listes. Très vite, une question se pose : que faire des cellules qui ne sont plus accessibles ? Demander au programmeur de les libérer manuellement compliquerait fortement les fonctions récursives que McCarthy cherche justement à rendre simples.
Les premiers systèmes Lisp adoptent donc une récupération automatique de la mémoire. Lorsque la réserve de cellules libres s’épuise, le système repère les structures encore accessibles depuis le programme et récupère les autres. Le principe correspond à ce que l’on appellera couramment un garbage collector.
Cette gestion automatique a un coût sur les machines de l’époque, mais elle libère le programmeur d’une partie importante de l’administration de la mémoire. Bien avant Java, C# ou JavaScript, Lisp fait ainsi de la récupération automatique des objets inutilisés une composante normale de l’environnement d’exécution.
Un langage fait pour travailler de manière interactive
L’interpréteur change aussi la manière de programmer. Une fonction peut être saisie, exécutée, modifiée puis redéfinie sans reconstruire tout le programme. Cette méthode s’accorde particulièrement bien avec le temps partagé qui se développe au MIT durant les années 1960.
Le cycle de travail devient très direct : lire une expression, l’évaluer, afficher le résultat, recommencer. C’est le principe du REPL, pour Read-Eval-Print Loop, aujourd’hui familier dans de nombreux langages interactifs.
Lisp ne reste pas pour autant un langage seulement interprété. Timothy Hart et Michael Levin réalisent l’un des premiers compilateurs Lisp efficaces, lui-même écrit en Lisp. Les environnements ultérieurs combinent naturellement interprétation, compilation, débogage et modification interactive du programme.
Pourquoi Lisp devient-il le langage de l’intelligence artificielle ?
Lisp arrive au bon moment avec des mécanismes adaptés aux problèmes étudiés par les laboratoires d’IA : listes de longueur variable, symboles, arbres, récursion, fonctions manipulables, mémoire automatique et environnement interactif. L’article de McCarthy de 1960 cite déjà la vérification de preuves, la différentiation et l’intégration symboliques, la logique et l’Advice Taker parmi les usages visés.
Le langage se diffuse ensuite sur les machines utilisées par les grands laboratoires. Au MIT, les PDP-6 puis PDP-10 deviennent des plates-formes majeures pour Lisp et l’intelligence artificielle. Des systèmes de calcul symbolique comme Macsyma, des programmes de recherche, des outils de démonstration et de nombreux environnements expérimentaux sont développés dans cet univers.
Le Computer History Museum résume cette place en qualifiant Lisp de véritable lingua franca de l’IA de cette période. Son importance ne vient donc pas d’une obligation institutionnelle : le langage correspond simplement très bien au type de programmes que les chercheurs veulent écrire.
Quand on construit un ordinateur pour Lisp
À mesure que les programmes d’IA grossissent, les limites des machines généralistes deviennent plus visibles. Au MIT AI Lab, Richard Greenblatt, Thomas Knight et d’autres ingénieurs explorent une solution radicale : au lieu d’adapter Lisp à un ordinateur conçu pour autre chose, pourquoi ne pas construire un ordinateur adapté à Lisp ?
Greenblatt décrit en 1974 un projet de Lisp machine. Quelques années plus tard, les prototypes du MIT débouchent sur des stations de travail spécialisées. Elles ne se contentent pas d’accélérer l’exécution : elles proposent un environnement très intégré où l’on peut écrire, inspecter, compiler et déboguer de grands programmes de manière interactive.
Au début des années 1980, cette technologie est commercialisée notamment par Symbolics et Lisp Machines, Inc. Pendant quelques années, les Lisp machines incarnent une informatique haut de gamme destinée à l’IA. Leur marché restera spécialisé et perdra ensuite de son intérêt face à la progression rapide des stations de travail généralistes, mais leurs environnements de développement ont marqué toute une génération de programmeurs.
Lisp n’est pas un seul langage
Le nom Lisp désigne rapidement une famille. Les implémentations se multiplient et chacune adapte le langage à son environnement.
Maclisp, développé au MIT, joue un rôle central dans les années 1960 et 1970. Interlisp, issu des travaux de BBN puis développé à Xerox PARC, met fortement l’accent sur l’environnement interactif, l’édition et le débogage.
En 1975, Gerald Jay Sussman et Guy Steele présentent Scheme. Ce dialecte plus petit met notamment en avant la portée lexicale des variables, les fonctions comme valeurs de première classe et une utilisation particulièrement propre de la récursion terminale.
Au début des années 1980, la multiplication des dialectes devient un problème pour les gros logiciels. Plusieurs équipes cherchent alors un terrain commun. Le résultat est Common Lisp, décrit en 1984 par Guy Steele puis normalisé par l’ANSI en 1994. Le but n’est pas de remplacer toute la famille Lisp, mais de fournir une base stable et portable pour des applications importantes.
De Lisp à Emacs, AutoCAD et Clojure
La famille ne reste pas enfermée dans les laboratoires d’intelligence artificielle. Emacs Lisp, fortement inspiré de Maclisp, devient le langage d’extension de GNU Emacs. Une grande partie du comportement de l’éditeur peut ainsi être modifiée par l’utilisateur avec le même langage qui sert à l’application elle-même.
Dans les années 1980, Autodesk choisit Lisp pour étendre AutoCAD. AutoLISP permet d’automatiser des tâches de dessin et d’ajouter des commandes spécialisées. Il est encore pris en charge aujourd’hui dans les produits AutoCAD.
En 2007, Rich Hickey présente Clojure, un Lisp destiné à la JVM. Le langage conserve le principe du code représenté comme des données et les macros, mais l’associe à des structures persistantes immuables et à des mécanismes conçus pour la programmation concurrente. Lisp n’est donc pas seulement un langage historique : c’est une idée de langage qui continue d’être réinterprétée.
Les limites : une élégance qui demande un apprentissage
La syntaxe uniforme de Lisp simplifie son analyse par la machine, mais elle déroute souvent le débutant. Un programme important peut contenir beaucoup de parenthèses et la notation préfixée demande un temps d’adaptation.
La famille Lisp a aussi longtemps souffert de sa fragmentation. Maclisp, Interlisp, Scheme, Common Lisp, Emacs Lisp ou AutoLISP partagent des idées communes sans être interchangeables. Un programme écrit dans l’un ne fonctionne pas automatiquement dans les autres.
Les premières implémentations étaient en outre peu performantes pour le calcul numérique par rapport à FORTRAN. McCarthy reconnaissait déjà cette faiblesse dans l’histoire du langage. Les compilateurs modernes ont largement changé la situation, mais l’image d’un Lisp lent et gourmand en mémoire s’est installée durablement.
Enfin, la puissance des macros possède son revers. Elles permettent d’adapter le langage au problème, mais un programme abusant de constructions très personnelles peut devenir difficile à lire pour quelqu’un qui ne connaît pas ces extensions.
Un héritage beaucoup plus large que ses parenthèses
L’influence de Lisp ne se mesure pas seulement au nombre de programmes encore écrits en Common Lisp ou en Scheme. Plusieurs idées devenues ordinaires dans la programmation moderne ont été explorées très tôt et de manière systématique dans son écosystème : gestion automatique de la mémoire, fonctions comme valeurs, récursion, développement interactif, représentation structurée des programmes et macros capables de transformer le code.
Toutes ces idées n’ont pas été inventées isolément par Lisp. Certaines viennent des mathématiques, d’autres existaient dans des travaux antérieurs. Lisp les a cependant réunies dans un système cohérent et utilisable sur de vraies machines à une époque où la plupart des langages de programmation suivaient une direction très différente.
En 1980, John McCarthy expliquait la longévité de Lisp par le fait que le langage avait trouvé une combinaison particulièrement stable de mécanismes. Plus de soixante ans après les premières implémentations, le constat reste pertinent : les dialectes ont changé, les machines n’ont plus rien à voir avec l’IBM 704, mais l’idée centrale est toujours reconnaissable.
Derrière les parenthèses se trouve une proposition simple : si un programme est représenté comme une structure de données, le langage peut aussi devenir un outil pour examiner, transformer et construire ses propres programmes. C’est cette idée, bien plus que sa syntaxe, qui donne à Lisp sa place particulière dans l’histoire de l’informatique.
Sources principales
- John McCarthy, History of Lisp, texte présenté à la conférence ACM sur l’histoire des langages de programmation.
- John McCarthy, Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I, Communications of the ACM, 1960.
- John McCarthy, Paul W. Abrahams, Daniel J. Edwards, Timothy P. Hart et Michael I. Levin, LISP 1.5 Programmer’s Manual, MIT Press, 1962.
- Richard Greenblatt, The LISP Machine, MIT Artificial Intelligence Laboratory, 1974.
- Gerald Jay Sussman et Guy L. Steele Jr., SCHEME: An Interpreter for Extended Lambda Calculus, MIT AI Memo 349, 1975.
- Common Lisp HyperSpec, historique et standardisation de Common Lisp.
- GNU Emacs Lisp Reference Manual : Lisp History.
- Autodesk : AutoLISP and Visual LISP.
- Clojure : Rationale, présentation des choix de conception de Clojure.
- Computer History Museum : Creating the Tools for AI, Lisp et les Lisp machines.
À lire aussi sur Histoire de l’Informatique
- Histoire de l’intelligence artificielle : de Turing à ChatGPT
- Dartmouth College : BASIC, time-sharing et naissance de l’IA
- MIT : informatique interactive, hackers et intelligence artificielle
- Richard Greenblatt : Mac Hack, Lisp et Lisp machines
- PDP-6 : l’ordinateur 36 bits de DEC
- PDP-10 : l’ordinateur qui équipa les grands laboratoires
