CE QUI RENDAIT LISP DIFFÉRENT
OriginalDecember 2001 (rev. May 2002)
(Cet article est né en réponse à certaines 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. Conditionnels. Un conditionnel est une construction if-then-else. Nous les tenons pour acquis maintenant. Ils ont été inventés par McCarthy au cours 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 était membre du comité Algol, a fait entrer les conditionnels dans Algol, d'où ils se sont répandus dans la plupart des autres langages.
2. Un type de fonction. Dans Lisp, les fonctions sont des objets de première classe
- elles sont un type de données tout 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, et ainsi de suite.
3. Récursion. La récursion existait en tant que concept mathématique avant Lisp bien sûr, mais Lisp a été le premier langage de programmation à la supporter. (On peut dire qu'elle est 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 effectivement des pointeurs. Les valeurs sont ce qui a des types, pas les variables, et assigner ou lier des variables signifie copier des pointeurs, pas ce à quoi ils pointent.
5. Collecte des ordures.
6. Programmes composés d'expressions. Les programmes Lisp sont des arbres d'expressions, chacune d'elles retournant une valeur. (Dans certains Lisps, les expressions peuvent retourner plusieurs valeurs.) Cela contraste avec Fortran et la plupart des langages suivants, qui distinguent entre expressions et instructions.
Il était naturel d'avoir cette distinction dans Fortran parce que (pas surprenant 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, bien que vous ayez 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 retourne une valeur, car il ne pouvait y avoir rien qui l'attende.
Cette limitation a disparu avec l'arrivée des langages à structure de blocs, mais à ce moment-là, il était trop tard. La distinction entre expressions et instructions était ancrée. Elle s'est répandue de Fortran à Algol et ensuite à 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 en ce que vous pouvez tester l'égalité en comparant un pointeur.
8. Une notation pour le code utilisant des arbres de symboles.
9. L'ensemble du langage 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 tout en lisant, lire ou exécuter du code tout en compilant, 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 en tant que 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 forme de XML.
Lorsque Lisp a été inventé pour la première fois, toutes ces idées étaient loin des pratiques de programmation ordinaires, qui étaient dictées 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 répandus. 6 commence à apparaître dans le grand public. 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 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 que utile aux programmeurs d'aujourd'hui, il est étrange de décrire Lisp en termes de sa 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 né comme un sous-produit d'une tentative de axiomatiser le calcul.