QU'EST-CE QUI A RENDU LISP DIFFÉRENT
OriginalDécembre 2001 (rév. Mai 2002)
(Cet article a été rédigé en réponse à des questions sur la liste de diffusion LL1. Il est maintenant incorporé dans Revenge of the Nerds.)
Lorsque McCarthy a conçu Lisp à la fin des années 1950, c'était un départ radical par rapport aux langages existants, le plus important étant Fortran.
Lisp incarnait neuf nouvelles idées :
1. Les conditionnelles. Une conditionnelle est une construction de type if-then-else. Nous les tenons pour acquises maintenant. Elles ont été inventées par McCarthy dans le cadre du développement de Lisp. (Fortran à l'époque n'avait qu'un goto conditionnel, étroitement basé sur l'instruction de branchement dans le matériel sous-jacent.) McCarthy, qui faisait partie du comité Algol, a fait intégrer les conditionnelles dans Algol, d'où elles se sont répandues dans la plupart des autres langages.
2. Un type de fonction. Dans Lisp, les fonctions sont des objets de première classe
- ce sont un type de données comme les entiers, les chaînes, etc., et ont une représentation littérale, peuvent être stockées dans des variables, peuvent être passées en argument, et ainsi de suite.
3. La récursion. La récursion existait comme concept mathématique avant Lisp bien sûr, mais Lisp a été le premier langage de programmation à la prendre en charge. (C'est peut-être implicite dans le fait de faire des fonctions des objets de première classe.)
4. Un nouveau concept de variables. Dans Lisp, toutes les variables sont en fait des pointeurs. Les valeurs ont des types, pas les variables, et l'affectation ou la liaison des variables signifie copier des pointeurs, pas ce qu'ils pointent.
5. La collecte des déchets.
6. Des programmes composés d'expressions. Les programmes Lisp sont des arbres d'expressions, chacune renvoyant une valeur. (Dans certains Lisps, les expressions peuvent renvoyer plusieurs valeurs.) C'est à l'opposé de Fortran et de la plupart des langages qui ont suivi, qui distinguent entre expressions et instructions.
Il était naturel d'avoir cette distinction dans Fortran car (sans surprise dans un langage où le format d'entrée était des cartes perforées) le langage était orienté ligne. Vous ne pouviez pas imbriquer d'instructions. Et donc, bien que vous ayez besoin d'expressions pour que les mathématiques fonctionnent, il n'y avait pas de raison de faire que quoi que ce soit d'autre renvoie une valeur, car il n'y avait rien qui l'attendait.
Cette limitation a disparu avec l'arrivée des langages à structure de blocs, mais c'était alors trop tard. La distinction entre expressions et instructions était ancrée. Elle s'est répandue de Fortran dans Algol et de là dans leurs descendants.
Lorsqu'un langage est entièrement composé d'expressions, vous pouvez composer les expressions comme vous le voulez. Vous pouvez dire soit (en utilisant la syntaxe Arc)
(if foo (= x 1) (= x 2))
soit
(= x (if foo 1 2))
7. Un type de symbole. Les symboles diffèrent des chaînes en ce que vous pouvez tester l'égalité en comparant un pointeur.
8. Une notation pour le code utilisant des arbres de symboles.
9. Toute la langue toujours disponible. Il n'y a pas de véritable distinction entre le temps de lecture, le temps de compilation et le temps d'exécution. Vous pouvez compiler ou exécuter du code pendant la lecture, lire ou exécuter du code pendant la compilation, et lire ou compiler du code à l'exécution.
Exécuter du code au moment de la lecture permet aux utilisateurs de reprogrammer la syntaxe de Lisp ; exécuter du code au moment de la compilation est la base des macros ; compiler à l'exécution est la base de l'utilisation de Lisp comme langage d'extension dans des programmes comme Emacs ; et lire à l'exécution permet aux programmes de communiquer en utilisant des s-expressions, une idée récemment réinventée sous le nom de XML.
Lorsque Lisp a été inventé pour la première fois, toutes ces idées étaient très éloignées de la pratique de programmation ordinaire, qui était largement dictée par le matériel disponible à la fin des années 1950.
Au fil du temps, le langage par défaut, incarné dans une succession de langages populaires, a progressivement évolué vers Lisp. 1-5 sont maintenant répandus. 6 commence à apparaître dans le courant dominant. Python a une forme de 7, bien qu'il ne semble pas y avoir de syntaxe pour cela. 8, qui (avec 9) est ce qui rend les macros Lisp possibles, est jusqu'à présent encore unique à Lisp, peut-être parce que (a) il nécessite ces parenthèses, ou quelque chose d'aussi mauvais, et (b) si vous ajoutez cet ultime incrément de puissance, vous ne pouvez plus prétendre avoir inventé un nouveau langage, mais seulement avoir conçu un nouveau dialecte de Lisp ; -)
Bien qu'utiles pour les programmeurs d'aujourd'hui, il est étrange de décrire Lisp en termes de ses variations par rapport aux expédients aléatoires que d'autres langages ont adoptés. Ce n'était probablement pas ainsi que McCarthy le voyait. Lisp n'a pas été conçu pour corriger les erreurs de Fortran ; il est apparu plutôt comme le sous-produit d'une tentative d'axiomatiser le calcul.