CE QUI REND LISP DIFFÉRENT
OriginalDécembre 2001 (révisé en mai 2002)
(Cet article a été rédigé en réponse à certaines questions sur la liste de diffusion LL1 . Il est désormais intégré à Revenge of the Nerds .)
Lorsque McCarthy a conçu Lisp à la fin des années 1950, il s'agissait d'un changement radical par rapport aux langages existants, dont le plus important était Fortran .
Lisp a incarné neuf nouvelles idées :
1. Les conditions. Une condition est une construction if-then-else. Nous les tenons pour acquis aujourd'hui. Elles ont été inventées par McCarthy au cours du développement de Lisp. (Fortran n'avait à l'époque qu'une condition goto, étroitement basée sur l'instruction de branchement dans le matériel sous-jacent.) McCarthy, qui faisait partie du comité Algol, a introduit les conditions 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 tant qu'arguments, etc.
3. Récursivité. La récursivité existait bien sûr en tant que concept mathématique avant Lisp, mais Lisp a été le premier langage de programmation à la prendre en charge. (On peut dire qu'elle est implicite dans la transformation des fonctions en objets de première classe.)
4. Un nouveau concept de variables. En Lisp, toutes les variables sont en fait des pointeurs. Les valeurs sont ce qui possède un type, pas des variables, et l'affectation ou la liaison de variables signifie copier des pointeurs, pas ce vers quoi ils pointent.
5. Collecte des déchets.
6. Programmes composés d'expressions. Les programmes Lisp sont des arbres d'expressions, chacune d'elles renvoyant une valeur. (Dans certains programmes Lisp, les expressions peuvent renvoyer plusieurs valeurs.) Cela contraste avec Fortran et la plupart des langages suivants, qui font la distinction entre les expressions et les instructions.
Il était naturel d'avoir cette distinction en Fortran car (ce qui n'est pas surprenant dans un langage où le format d'entrée était des cartes perforées) le langage était orienté ligne. On ne pouvait pas imbriquer des instructions. Et donc, même si on avait besoin d'expressions pour que les mathématiques fonctionnent, il n'y avait aucun intérêt à faire en sorte que quoi que ce soit d'autre renvoie une valeur, car rien ne pouvait l'attendre.
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 ancrée. Elle s'est propagée de Fortran à Algol, puis à leurs deux descendants.
Lorsqu'un langage est entièrement constitué d'expressions, vous pouvez composer des expressions comme vous le souhaitez. Vous pouvez dire l'une ou l'autre (en utilisant la syntaxe Arc )
(si foo (= x 1) (= x 2))
ou
(= x (si foo 1 2))
7. Un type de symbole. Les symboles diffèrent des chaînes dans la mesure où vous pouvez tester l'égalité en comparant un pointeur.
8. Une notation pour le code utilisant des arbres de symboles.
9. L'intégralité du langage est toujours disponible. Il n'y a pas de réelle distinction entre la lecture, la compilation et l'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 pendant 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 au moment de l'exécution est la base de l'utilisation de Lisp comme langage d'extension dans des programmes comme Emacs ; et la lecture au moment de 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é, toutes ces idées étaient très éloignées de la pratique de programmation ordinaire, qui était en grande partie 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. Les langages 1 à 5 sont maintenant très répandus. Le 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. Le 8, qui (avec le 9) est ce qui rend les macros Lisp possibles, est jusqu'à présent unique à Lisp, peut-être parce que (a) il nécessite ces parenthèses, ou quelque chose d'aussi mauvais, et (b) si vous ajoutez ce dernier 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'utile pour les programmeurs d'aujourd'hui, il est étrange de décrire Lisp en termes de variation par rapport aux expédients aléatoires adoptés par d'autres langages. Ce n'était probablement pas ainsi que McCarthy l'envisageait. Lisp n'a pas été conçu pour corriger les erreurs de Fortran ; il est plutôt le résultat d'une tentative d' axiomatisation du calcul .