CE QUI A RENDU LISP DIFFÉRENT
OriginalDécembre 2001 (rev. Mai 2002)
(Cet article a été écrit en réponse à quelques questions sur la liste de diffusion LL1. Il est maintenant inclus dans Revenge of the Nerds.)
Lorsque McCarthy a conçu Lisp à la fin des années 1950, c'était un départ radical des langages existants, dont le plus important était Fortran.
Lisp incarnait neuf nouvelles idées :
1. Conditionnelles. Une conditionnelle est une construction if-then-else. Nous les tenons pour acquises maintenant. Elles ont été inventées par McCarthy au cours du développement de Lisp. (Fortran à cette é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 entrer les conditionnelles dans Algol, d'où elles se sont répandues dans la plupart des autres langages.
2. Un type de fonction. En Lisp, les fonctions sont des objets de première classe -- elles 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 arguments, etc.
3. Récursivité. La récursivité existait en tant que concept mathématique avant Lisp bien sûr, mais Lisp était le premier langage de programmation à la prendre en charge. (C'est sans doute implicite dans le fait de faire des fonctions des objets de première classe.)
4. Un nouveau concept de variables. En Lisp, toutes les variables sont effectivement des pointeurs. Les valeurs sont ce qui a des types, pas les variables, et l'affectation ou la liaison des variables signifie copier des pointeurs, pas ce vers quoi ils pointent.
5. Ramasse-miettes.
6. Programmes composés d'expressions. Les programmes Lisp sont des arbres d'expressions, dont chacune renvoie une valeur. (Dans certains Lisps, les expressions peuvent renvoyer plusieurs valeurs.) Ceci contraste avec Fortran et la plupart des langages qui ont suivi, qui distinguent entre expressions et instructions.
Il était naturel d'avoir cette distinction dans Fortran parce que (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 des instructions. Et donc, alors que vous aviez besoin d'expressions pour que les mathématiques fonctionnent, il n'y avait pas de raison de faire en sorte que quoi que ce soit d'autre renvoie une valeur, car il ne pouvait rien y avoir qui l'attende.
Cette limitation a disparu avec l'arrivée des langages structurés en blocs, mais il était alors trop tard. La distinction entre expressions et instructions était bien établie. 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 des expressions comme vous le souhaitez. Vous pouvez dire soit (en utilisant la syntaxe Arc)
(if foo (= x 1) (= x 2))
ou
(= x (if foo 1 2))
7. Un type de symbole. Les symboles diffèrent des chaînes de caractères en ce que vous pouvez tester l'égalité en comparant un pointeur.
8. Une notation pour le code utilisant des arbres de symboles.
9. Le langage entier toujours disponible. Il n'y a pas de réelle 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.
L'exécution de code au moment de la lecture permet aux utilisateurs de reprogrammer la syntaxe de Lisp ; l'exécution de code au moment de la compilation est à la base des macros ; la compilation à l'exécution est à la base de l'utilisation de Lisp comme langage d'extension dans des programmes comme Emacs ; et la lecture à 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 loin de la pratique de programmation ordinaire, qui était dictée en grande partie 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 évolué progressivement vers Lisp. 1-5 sont maintenant largement 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) cela nécessite ces parenthèses, ou quelque chose d'aussi mauvais, et (b) si vous ajoutez cet incrément final 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'utile pour les programmeurs d'aujourd'hui, il est étrange de décrire Lisp en termes de sa variation 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 né davantage comme un sous-produit d'une tentative d'axiomatisation du calcul.