Lisp commun

Common Lisp ( CL ) est un dialecte du langage de programmation Lisp , publié dans le document standard ANSI ANSI INCITS 226-1994 (S20018) [1] (anciennement X3.226-1994 (R1999) ). [2] Le Common Lisp HyperSpec , une version HTML hyperliée, a été dérivé de la norme ANSI Common Lisp. [3]

Lisp commun
Paradigme Multi-paradigme : procédural , fonctionnel , orienté objet , méta , réflexif , générique
Famille Zézayer
Conçu par Scott Fahlman , Richard P. Gabriel , David A. Moon , Kent Pitman , Guy Steele , Dan Weinreb
Développeur Comité ANSI X3J13
Première apparition 1984 (il y a 38 ans) , 1994 (il y a 28 ans) pour ANSI Common Lisp ( 1984 ) ( 1994 )
Discipline de frappe Dynamique , fort
Portée Lexique, éventuellement dynamique
SE Multiplateforme
Extensions de nom de fichier .lisp, .lsp, .l, .cl, .fasl
Site Internet lisp commun .net
Principales implémentations
Allegro CL , ABCL , CLISP , Clozure CL , CMUCL , ECL , GCL , LispWorks , Scieneer CL , SBCL , Symbolics Common Lisp
Dialectes
CLtL1, CLtL2, ANSI Common Lisp
Influencé par
Lisp , Lisp Machine Lisp , Maclisp , Schéma , Interlisp
Influencé
Clojure , Dylan , Emacs Lisp , EuLisp , ISLISP , *Lisp , AutoLisp , Julia , Moose , R , SKILL , SubL

Le langage Common Lisp a été développé en tant que successeur standardisé et amélioré de Maclisp . Au début des années 1980, plusieurs groupes travaillaient déjà sur divers successeurs de MacLisp : Lisp Machine Lisp (alias ZetaLisp), Spice Lisp , NIL et S-1 Lisp . Common Lisp a cherché à unifier, normaliser et étendre les fonctionnalités de ces dialectes MacLisp. Common Lisp n’est pas une implémentation, mais plutôt une spécification de langage . [4] Plusieurs implémentations de la norme Common Lisp sont disponibles, y compris des logiciels libres et open-source et des produits propriétaires. [5] Common Lisp est un usage général,Langage de programmation multi-paradigme . Il prend en charge une combinaison de paradigmes de programmation procédurale , fonctionnelle et orientée objet . En tant que langage de programmation dynamique , il facilite le développement de logiciels évolutifs et incrémentaux , avec une compilation itérative dans des programmes d’exécution efficaces. Ce développement incrémentiel est souvent effectué de manière interactive sans interrompre l’application en cours d’exécution.

Il prend également en charge l’annotation et le casting de type facultatifs, qui peuvent être ajoutés si nécessaire lors des étapes ultérieures de profilage et d’optimisation, pour permettre au compilateur de générer un code plus efficace. Par exemple, fixnumpeut contenir un entier sans boîte dans une plage prise en charge par le matériel et l’implémentation, permettant une arithmétique plus efficace que sur les grands entiers ou les types de précision arbitraires. De même, le compilateur peut être informé par module ou par fonction du type de niveau de sécurité souhaité, à l’aide de déclarations d’ optimisation .

Common Lisp inclut CLOS , un système objet qui prend en charge plusieurs méthodes et combinaisons de méthodes. Il est souvent implémenté avec un protocole Metaobject .

Common Lisp est extensible grâce à des fonctionnalités standard telles que les macros Lisp (transformations de code) et les macros de lecteur (analyseurs d’entrée pour les caractères).

Common Lisp offre une rétrocompatibilité partielle avec le Lisp original de Maclisp et John McCarthy . Cela permet aux anciens logiciels Lisp d’être portés sur Common Lisp. [6]

Histoire

Les travaux sur Common Lisp ont commencé en 1981 après une initiative du directeur de l’ARPA, Bob Engelmore, visant à développer un dialecte Lisp standard de la communauté unique. [7] Une grande partie de la conception initiale du langage a été réalisée par courrier électronique. [8] [9] En 1982, Guy L. Steele Jr. a donné le premier aperçu de Common Lisp au Symposium ACM de 1982 sur LISP et la programmation fonctionnelle. [dix]

La première documentation de langage a été publiée en 1984 sous le nom de Common Lisp the Language (connu sous le nom de CLtL1), première édition. Une deuxième édition (connue sous le nom de CLtL2), publiée en 1990, a incorporé de nombreuses modifications au langage, apportées au cours du processus de normalisation ANSI Common Lisp : syntaxe LOOP étendue, le Common Lisp Object system, le Condition System pour la gestion des erreurs, une interface vers le jolie imprimante et bien plus encore. Mais CLtL2 ne décrit pas la norme ANSI Common Lisp finale et n’est donc pas une documentation de l’ANSI Common Lisp. La norme ANSI Common Lisp finale a ensuite été publiée en 1994. Depuis lors, aucune mise à jour de la norme n’a été publiée. Diverses extensions et améliorations de Common Lisp (par exemple, Unicode, Concurrency, IO basé sur CLOS) ont été fournies par des implémentations et des bibliothèques.

Syntaxe

Common Lisp est un dialecte de Lisp. Il utilise des expressions S pour désigner à la fois le code et la structure des données. Les appels de fonction, les formes de macro et les formes spéciales sont écrites sous forme de listes, avec le nom de l’opérateur en premier, comme dans ces exemples :

( + 2 2 ) ; ajoute 2 et 2, ce qui donne 4. Le nom de la fonction est ‘+’. Lisp n’a pas d’opérateurs en tant que tels. ( defvar *x* ) ; Assure qu’une variable *x* existe, ; sans lui donner de valeur. Les astérisques font partie de ; le nom, par convention désignant une variable spéciale (globale). ; Le symbole *x* est également doté de la propriété que ; ses liaisons ultérieures sont dynamiques plutôt que lexicales. ( setf *x* 42.1 ) ; Définit la variable *x* sur la valeur à virgule flottante 42.1 ;; Définissez une fonction qui met au carré un nombre : ( defun square ( x ) ( * x x )) ;; Exécutez la fonction : ( carré 3 ) ; Retourne 9 ;; La construction ‘let’ crée une portée pour les variables locales. Ici ;; la variable ‘a’ est liée à 6 et la variable ‘b’ est liée ;; à 4. À l’intérieur du ‘let’ se trouve un ‘body’, où la dernière valeur calculée est renvoyée. ;; Ici, le résultat de l’ajout de a et b est renvoyé à partir de l’expression ‘let’. ;; Les variables a et b ont une portée lexicale, sauf si les symboles ont été ;; marquées comme des variables spéciales (par exemple par un DEFVAR préalable). ( soit (( une 6 ) ( b 4 )) ( + une b )) ; renvoie 10

Types de données

Common Lisp a de nombreux types de données .

Types scalaires

Les types de nombres incluent les entiers , les ratios , les nombres à virgule flottante et les nombres complexes . [11] Common Lisp utilise des bignums pour représenter des valeurs numériques de taille et de précision arbitraires. Le type de rapport représente exactement les fractions, une fonctionnalité non disponible dans de nombreuses langues. Common Lisp contraint automatiquement les valeurs numériques parmi ces types, le cas échéant.

Le type de caractère Common Lisp n’est pas limité aux caractères ASCII . La plupart des implémentations modernes autorisent les caractères Unicode . [12]

Le type de symbole est commun aux langages Lisp, mais largement inconnu en dehors d’eux. Un symbole est un objet de données unique et nommé composé de plusieurs parties : nom, valeur, fonction, liste de propriétés et package. Parmi celles-ci, la cellule de valeur et la cellule de fonction sont les plus importantes. Les symboles en Lisp sont souvent utilisés de la même manière que les identifiants dans d’autres langages : pour contenir la valeur d’une variable ; cependant, il existe de nombreuses autres utilisations. Normalement, lorsqu’un symbole est évalué, sa valeur est renvoyée. Certains symboles s’auto-évaluent, par exemple, tous les symboles du package de mots-clés s’auto-évaluent. Les valeurs booléennes en Common Lisp sont représentées par les symboles d’auto-évaluation T et NIL. Common Lisp a des Espaces de noms pour les symboles, appelés « packages ».

Un certain nombre de fonctions sont disponibles pour arrondir les valeurs numériques scalaires de différentes manières. La fonction roundarrondit l’argument à l’entier le plus proche, avec des cas intermédiaires arrondis à l’entier pair. Les fonctions truncate, flooret ceilingarrondissent respectivement vers zéro, vers le bas ou vers le haut. Toutes ces fonctions renvoient la partie fractionnaire ignorée comme valeur secondaire. Par exemple, (floor -2.5)donne -3, 0,5 ; (ceiling -2.5)donne -2, -0,5 ; (round 2.5)donne 2, 0,5 ; et (round 3.5)donne 4, -0,5.

Structures de données

Les types de séquence dans Common Lisp incluent les listes, les vecteurs, les vecteurs de bits et les chaînes. De nombreuses opérations peuvent fonctionner sur n’importe quel type de séquence.

Comme dans presque tous les autres dialectes Lisp, les listes en Common Lisp sont composées de conses , parfois appelées cellules ou paires de cons . A cons est une structure de données avec deux slots, appelés sa voiture et cdr . Une liste est une chaîne liée de cons ou la liste vide. La voiture de chaque contre fait référence à un membre de la liste (éventuellement une autre liste). Le cdr de chaque contre fait référence au contre suivant, à l’exception du dernier contre d’une liste, dont le cdr fait référence à la nilvaleur. Conses peut également être facilement utilisé pour implémenter des arbres et d’autres structures de données complexes ; bien qu’il soit généralement conseillé d’utiliser des instances de structure ou de classe à la place. Il est également possible de créer des structures de données circulaires avec des inconvénients.

Common Lisp prend en charge les tableaux multidimensionnels et peut redimensionner dynamiquement les tableaux ajustables si nécessaire. Les tableaux multidimensionnels peuvent être utilisés pour les mathématiques matricielles. Un vecteur est un tableau à une dimension. Les tableaux peuvent contenir n’importe quel type en tant que membres (même des types mixtes dans le même tableau) ou peuvent être spécialisés pour contenir un type spécifique de membres, comme dans un vecteur de bits. Généralement, seuls quelques types sont pris en charge. De nombreuses implémentations peuvent optimiser les fonctions de tableau lorsque le tableau utilisé est spécialisé dans le type. Deux types de tableaux spécialisés par type sont standard : une chaîne est un vecteur de caractères, tandis qu’un vecteur de bits est un vecteur de bits .

Les tables de hachage stockent les associations entre les objets de données. Tout objet peut être utilisé comme clé ou valeur. Les tables de hachage sont automatiquement redimensionnées selon les besoins.

Les packages sont des collections de symboles, utilisés principalement pour séparer les parties d’un programme en Espaces de noms . Un package peut exporter certains symboles, les marquant comme faisant partie d’une interface publique. Les packages peuvent utiliser d’autres packages.

Les structures , similaires aux structures C et aux enregistrements Pascal , représentent des structures de données complexes arbitraires avec n’importe quel nombre et type de champs (appelés slots ). Les structures permettent l’héritage unique.

Les classes sont similaires aux structures, mais offrent des fonctionnalités plus dynamiques et un héritage multiple. (Voir CLOS ). Les classes ont été ajoutées tardivement à Common Lisp et il y a un certain chevauchement conceptuel avec les structures. Les objets créés à partir de classes sont appelés Instances . Un cas particulier est celui des fonctions génériques. Les fonctions génériques sont à la fois des fonctions et des instances.

Les fonctions

Common Lisp prend en charge les fonctions de première classe . Par exemple, il est possible d’écrire des fonctions qui prennent d’autres fonctions comme arguments ou renvoient également des fonctions. Cela permet de décrire des opérations très générales.

La bibliothèque Common Lisp s’appuie fortement sur ces fonctions d’ordre supérieur. Par exemple, la sortfonction prend un opérateur relationnel comme argument et une fonction clé comme argument mot-clé facultatif. Cela peut être utilisé non seulement pour trier n’importe quel type de données, mais aussi pour trier les structures de données selon une clé.

;; Trie la liste en utilisant la fonction > et < comme opérateur relationnel. ( trier ( liste 5 2 6 3 1 4 ) #’ > ) ; Renvoie (6 5 4 3 2 1) ( sort ( liste 5 2 6 3 1 4 ) #’ < ) ; Retours (1 2 3 4 5 6) ;; Trie la liste en fonction du premier élément de chaque sous-liste. ( trier ( liste ‘ ( 9 A ) ‘ ( 3 B ) ‘ ( 4 C )) #’ < :clé #’ premier ) ; Retours ((3 B) (4 C) (9 A))

Le modèle d’évaluation des fonctions est très simple. Lorsque l’évaluateur rencontre un formulaire (f a1 a2…), il présume que le symbole nommé f est l’un des suivants :

  1. Un opérateur spécial (facilement vérifié par rapport à une liste fixe)
  2. Un opérateur macro (doit avoir été défini au préalable)
  3. Le nom d’une fonction (par défaut), qui peut être soit un symbole, soit un sous-formulaire commençant par le symbole lambda.

Si f est le nom d’une fonction, alors les arguments a1, a2, …, an sont évalués dans l’ordre de gauche à droite, et la fonction est trouvée et invoquée avec ces valeurs fournies comme paramètres.

Définition des fonctions

La macrodefun définit des fonctions où une définition de fonction donne le nom de la fonction, les noms de tous les arguments et un corps de fonction :

( carré defun ( x ) ( * x x ))

Les définitions de fonction peuvent inclure des directives de compilateur , appelées déclarations , qui fournissent des indications au compilateur sur les paramètres d’optimisation ou les types de données des arguments. Ils peuvent également inclure des chaînes de documentation (docstrings), que le système Lisp peut utiliser pour fournir une documentation interactive :

( defun square ( x ) “Calcule le carré du single-float x.” ( declare ( single-float x ) ( optimize ( speed 3 ) ( debug 0 ) ( safety 1 ))) ( the single-float ( * x x )))

Les fonctions anonymes ( littéraux de fonction ) sont définies à l’aide d’ lambdaexpressions, par exemple (lambda (x) (* x x))pour une fonction qui élève au carré son argument. Le style de programmation Lisp utilise fréquemment des fonctions d’ordre supérieur pour lesquelles il est utile de fournir des fonctions anonymes comme arguments.

Les fonctions locales peuvent être définies avec fletet labels.

( flet (( carré ( x ) ( * x x ))) ( carré 3 ))

Il existe plusieurs autres opérateurs liés à la définition et à la manipulation des fonctions. Par exemple, une fonction peut être compilée avec l’ compileopérateur. (Certains systèmes Lisp exécutent des fonctions en utilisant un interpréteur par défaut, sauf instruction de compiler ; d’autres compilent chaque fonction).

Définir des fonctions et des méthodes génériques

La macro defgenericdéfinit des fonctions génériques . Les fonctions génériques sont une collection de méthodes . La macro defmethoddéfinit les méthodes.

Les méthodes peuvent spécialiser leurs paramètres sur les classes standard CLOS , les classes système , les classes de structure ou les objets individuels. Pour de nombreux types, il existe des classes système correspondantes .

Lorsqu’une fonction générique est appelée, l’envoi multiple déterminera la méthode efficace à utiliser.

( ajout défgénérique ( a b )) ( defmethod add (( un nombre ) ( b nombre )) ( + a b )) ( defmethod add (( a vector ) ( b number )) ( map ‘vector ( lambda ( n ) ( + n b )) a )) ( defmethod add (( a vector ) ( b vector )) ( map ‘vector #’ + a b )) ( defmethod add (( une chaîne ) ( b chaîne )) ( concaténer ‘chaîne a b )) ( ajouter 2 3 ) ; renvoie 5 ( ajouter #( 1 2 3 4 ) 7 ) ; renvoie #(8 9 10 11) ( ajouter #( 1 2 3 4 ) #( 4 3 2 1 )) ; renvoie #(5 5 5 5) ( ajouter “COMMON ” “LISP” ) ; renvoie “LISP COMMUN”

Les fonctions génériques sont également un type de données de première classe . Il y a beaucoup plus de fonctionnalités dans les fonctions et méthodes génériques que celles décrites ci-dessus.

L’espace de noms de la fonction

L’espace de noms pour les noms de fonction est distinct de l’espace de noms pour les variables de données. C’est une différence clé entre Common Lisp et Scheme . Pour Common Lisp, les opérateurs qui définissent les noms dans l’espace de noms de fonction incluent defun, flet, labelset .defmethoddefgeneric

Pour passer une fonction par son nom comme argument à une autre fonction, il faut utiliser l’ functionopérateur spécial, communément abrégé en #’. Le premier sortexemple ci-dessus fait référence à la fonction nommée par le symbole >dans l’espace de noms de la fonction, avec le code #’>. Inversement, pour appeler une fonction passée de cette manière, on utiliserait l’ funcallopérateur sur l’argument.

Le modèle d’évaluation de Scheme est plus simple : il n’y a qu’un seul espace de noms et toutes les positions du formulaire sont évaluées (dans n’importe quel ordre) – pas seulement les arguments. Le code écrit dans un dialecte est donc parfois déroutant pour les programmeurs plus expérimentés dans l’autre. Par exemple, de nombreux programmeurs Common Lisp aiment utiliser des noms de variables descriptifs tels que liste ou chaîne qui pourraient causer des problèmes dans Scheme, car ils masqueraient localement les noms de fonction.

La question de savoir si un espace de noms séparé pour les fonctions est un avantage est une source de discorde dans la communauté Lisp. Il est généralement appelé le débat Lisp-1 contre Lisp-2 . Lisp-1 fait référence au modèle de Scheme et Lisp-2 fait référence au modèle de Common Lisp. Ces noms ont été inventés dans un article de 1988 de Richard P. Gabriel et Kent Pitman , qui compare en détail les deux approches. [13]

Plusieurs valeurs de retour

Common Lisp prend en charge le concept de valeurs multiples , [14] où toute expression a toujours une seule valeur primaire , mais elle peut également avoir n’importe quel nombre de valeurs secondaires , qui peuvent être reçues et inspectées par les appelants intéressés. Ce concept est distinct du renvoi d’une valeur de liste, car les valeurs secondaires sont entièrement facultatives et transmises via un canal latéral dédié. Cela signifie que les appelants peuvent rester totalement inconscients de la présence de valeurs secondaires s’ils n’en ont pas besoin, et il est commode d’utiliser le mécanisme de communication d’informations parfois utiles, mais pas toujours nécessaires. Par example,

  • La TRUNCATEfonction [15] arrondit le nombre donné à un entier vers zéro. Cependant, il renvoie également un reste en tant que valeur secondaire, ce qui permet de déterminer très facilement quelle valeur a été tronquée. Il prend également en charge un paramètre de diviseur facultatif, qui peut être utilisé pour effectuer une division euclidienne de manière triviale :

( let (( x 1266778 ) ( y 458 )) ( multiple-value-bind ( quotient rest ) ( tronquer x y ) ( format nil “~A divisé par ~A est ~A reste ~A” x y quotient reste )) ) ;;;; => “1266778 divisé par 458 donne 2765 reste 408”

  • GETHASH[16] renvoie la valeur d’une clé dans une carte associative , ou la valeur par défaut sinon, et un booléen secondaire indiquant si la valeur a été trouvée. Ainsi, le code qui ne se soucie pas de savoir si la valeur a été trouvée ou fournie par défaut peut simplement l’utiliser telle quelle, mais lorsqu’une telle distinction est importante, il peut inspecter le booléen secondaire et réagir de manière appropriée. Les deux cas d’utilisation sont pris en charge par le même appel et aucun n’est inutilement alourdi ou contraint par l’autre. Le fait d’avoir cette fonctionnalité au niveau du langage supprime le besoin de vérifier l’existence de la clé ou de la comparer à null comme cela se ferait dans d’autres langages.

( defun get-answer ( bibliothèque ) ( gethash ‘réponse bibliothèque 42 )) ( defun the-answer-1 ( bibliothèque ) ( format nil “La réponse est ~A” ( bibliothèque get-answer ))) ;;;; Renvoie “La réponse est 42” si ANSWER n’est pas présent dans LIBRARY ( defun the-answer-2 ( library ) ( multiple-value-bind ( answer sure-p ) ( get-answer library ) ( if ( not sure-p ) “Je ne sais pas” ( format nil ” La réponse est ~Une” réponse )))) ;;;; Renvoie “Je ne sais pas” si ANSWER n’est pas présent dans LIBRARY

Les valeurs multiples sont prises en charge par une poignée de formes standard, dont les plus courantes sont la MULTIPLE-VALUE-BINDforme spéciale pour accéder aux valeurs secondaires et VALUESpour renvoyer plusieurs valeurs :

( defun magic-eight-ball () “Renvoie une prédiction de perspectives, avec la probabilité comme valeur secondaire” ( values ​​”Outlook good” ( random 1.0 ))) ;;;; => “Perspectives bonnes” ;;;; => 0,3187

Autres types

Les autres types de données dans Common Lisp incluent :

  • Les noms de chemin représentent des fichiers et des répertoires dans le système de fichiers . La fonction de nom de chemin Common Lisp est plus générale que les conventions de dénomination de fichiers de la plupart des systèmes d’exploitation, ce qui rend l’accès des programmes Lisp aux fichiers largement portable sur divers systèmes.
  • Les flux d’entrée et de sortie représentent les sources et les puits de données binaires ou textuelles, telles que le terminal ou les fichiers ouverts.
  • Common Lisp a un générateur de nombres pseudo-aléatoires (PRNG) intégré. Les objets d’ état aléatoires représentent des sources réutilisables de nombres pseudo-aléatoires, permettant à l’utilisateur d’amorcer le PRNG ou de lui faire rejouer une séquence.
  • Les conditions sont un type utilisé pour représenter des erreurs, des exceptions et d’autres événements “intéressants” auxquels un programme peut répondre.
  • Les classes sont des objets de première classe et sont elles-mêmes des instances de classes appelées classes de métaobjets ( métaclasses en abrégé).
  • Les tables de lecture sont un type d’objet qui contrôle la façon dont le lecteur de Common Lisp analyse le texte du code source. En contrôlant quelle table de lecture est utilisée lorsque le code est lu, le programmeur peut modifier ou étendre la syntaxe du langage.

Portée

Comme les programmes de nombreux autres langages de programmation, les programmes Common Lisp utilisent des noms pour désigner des variables, des fonctions et de nombreux autres types d’entités. Les références nommées sont soumises à la portée.

L’association entre un nom et l’entité à laquelle le nom fait référence s’appelle une liaison.

La portée fait référence à l’ensemble des circonstances dans lesquelles un nom est déterminé comme ayant une liaison particulière.

Déterminants de la portée

Les circonstances qui déterminent la portée dans Common Lisp incluent :

  • l’emplacement d’une référence dans une expression. S’il s’agit de la position la plus à gauche d’un composé, il fait référence à un opérateur spécial ou à une liaison de macro ou de fonction, sinon à une liaison de variable ou autre chose.
  • le type d’expression dans lequel la référence a lieu. Par exemple, (go x)signifie transférer le contrôle à l’étiquette x, tandis que (print x)fait référence à la variable x. Les deux portées de xpeuvent être actives dans la même région du texte du programme, car les étiquettes de corps de balise se trouvent dans un espace de noms distinct des noms de variables. Un formulaire spécial ou un formulaire de macro a un contrôle total sur la signification de tous les symboles de sa syntaxe. Par exemple, dans (defclass x (a b) ()), une définition de classe, (a b)est une liste de classes de base, donc ces noms sont recherchés dans l’espace des noms de classe, et xne sont pas une référence à une liaison existante, mais le nom d’une nouvelle classe dérivée de aet b. Ces faits ressortent purement de la sémantique dedefclass. Le seul fait générique concernant cette expression est qu’elle defclassfait référence à une liaison de macro ; tout le reste dépend de defclass.
  • l’emplacement de la référence dans le texte du programme. Par exemple, si une référence à une variable xest incluse dans une construction de liaison telle que a letqui définit une liaison pour x, alors la référence se trouve dans la portée créée par cette liaison.
  • pour une référence de variable, si oui ou non un symbole de variable a été, localement ou globalement, déclaré spécial. Cela détermine si la référence est résolue dans un environnement lexical ou dans un environnement dynamique.
  • l’instance spécifique de l’environnement dans lequel la référence est résolue. Un environnement est un dictionnaire d’exécution qui associe des symboles à des liaisons. Chaque type de référence utilise son propre type d’environnement. Les références aux variables lexicales sont résolues dans un environnement lexical, etc. Plusieurs environnements peuvent être associés à la même référence. Par exemple, grâce à la récursivité ou à l’utilisation de plusieurs threads, plusieurs activations d’une même fonction peuvent exister en même temps. Ces activations partagent le même texte de programme, mais chacune a sa propre instance d’environnement lexical.

Pour comprendre à quoi un symbole fait référence, le programmeur Common Lisp doit savoir quel type de référence est exprimé, quel type de portée il utilise s’il s’agit d’une référence variable (portée dynamique ou lexicale), et aussi la situation d’exécution : dans dans quel environnement la référence a-t-elle été résolue, où la liaison a-t-elle été introduite dans l’environnement, etc.

Types d’environnement

Mondial

Certains environnements en Lisp sont globalement omniprésents. Par exemple, si un nouveau type est défini, il est connu partout par la suite. Les références à ce type le recherchent dans cet environnement global.

Dynamique

Un type d’environnement dans Common Lisp est l’environnement dynamique. Les liaisons établies dans cet environnement ont une étendue dynamique, ce qui signifie qu’une liaison est établie au début de l’exécution d’une construction, telle qu’un letbloc, et disparaît lorsque cette construction finit de s’exécuter : sa durée de vie est liée à l’activation et à la désactivation dynamiques de un bloc. Cependant, une liaison dynamique n’est pas seulement visible dans ce bloc ; il est également visible pour toutes les fonctions appelées à partir de ce bloc. Ce type de visibilité est connu sous le nom de portée indéfinie. Les liaisons qui présentent une étendue dynamique (durée de vie liée à l’activation et à la désactivation d’un bloc) et une portée indéfinie (visible pour toutes les fonctions appelées à partir de ce bloc) sont dites avoir une portée dynamique.

Common Lisp prend en charge les variables à portée dynamique, également appelées variables spéciales. Certains autres types de liaisons ont nécessairement une portée dynamique également, comme les redémarrages et les balises catch. Les liaisons de fonctions ne peuvent pas être portées dynamiquement à l’aide flet(qui ne fournit que des liaisons de fonctions à portée lexicale), mais les objets de fonction (un objet de premier niveau dans Common Lisp) peuvent être affectés à des variables à portée dynamique, liés à l’aide letdans la portée dynamique, puis appelés à l’aide funcallou APPLY.

La portée dynamique est extrêmement utile car elle ajoute de la clarté référentielle et de la discipline aux variables globales . Les variables globales sont mal vues en informatique en tant que sources potentielles d’erreur, car elles peuvent donner lieu à des canaux de communication ad hoc et secrets entre les modules qui conduisent à des interactions indésirables et surprenantes.

En Common Lisp, une variable spéciale qui n’a qu’une liaison de niveau supérieur se comporte comme une variable globale dans d’autres langages de programmation. Une nouvelle valeur peut y être stockée, et cette valeur remplace simplement ce qui se trouve dans la liaison de niveau supérieur. Le remplacement imprudent de la valeur d’une variable globale est au cœur des bogues causés par l’utilisation de variables globales. Cependant, une autre façon de travailler avec une variable spéciale est de lui donner une nouvelle liaison locale dans une expression. Ceci est parfois appelé « reliaison » de la variable. La liaison d’une variable à portée dynamique crée temporairement un nouvel emplacement mémoire pour cette variable et associe le nom à cet emplacement. Tant que cette liaison est effective, toutes les références à cette variable font référence à la nouvelle liaison ; la liaison précédente est masquée. Lorsque l’exécution de l’expression de liaison se termine, l’emplacement de la mémoire temporaire a disparu et l’ancienne liaison est révélée, avec la valeur d’origine intacte. Bien sûr, plusieurs liaisons dynamiques pour la même variable peuvent être imbriquées.

Dans les implémentations Common Lisp qui prennent en charge le multithreading, les étendues dynamiques sont spécifiques à chaque thread d’exécution. Ainsi, les variables spéciales servent d’abstraction pour le stockage local des threads. Si un thread relit une variable spéciale, cette reliaison n’a aucun effet sur cette variable dans les autres threads. La valeur stockée dans une liaison ne peut être récupérée que par le thread qui a créé cette liaison. Si chaque thread lie une variable spéciale *x*, alors *x*se comporte comme un stockage local de thread. Parmi les threads qui ne se relient pas *x*, il se comporte comme un global ordinaire : tous ces threads font référence à la même liaison de niveau supérieur de *x*.

Les variables dynamiques peuvent être utilisées pour étendre le contexte d’exécution avec des informations de contexte supplémentaires qui sont implicitement transmises d’une fonction à l’autre sans avoir à apparaître comme paramètre de fonction supplémentaire. Ceci est particulièrement utile lorsque le transfert de contrôle doit passer par des couches de code sans rapport, qui ne peuvent tout simplement pas être étendues avec des paramètres supplémentaires pour transmettre les données supplémentaires. Une situation comme celle-ci nécessite généralement une variable globale. Cette variable globale doit être sauvegardée et restaurée, afin que le schéma ne se brise pas lors de la récursivité : la liaison de variable dynamique s’en charge. Et cette variable doit être rendue locale au thread (sinon un grand mutex doit être utilisé) afin que le schéma ne se brise pas sous les threads : les implémentations de portée dynamique peuvent également s’en occuper.

Dans la bibliothèque Common Lisp, il existe de nombreuses variables spéciales standard. Par exemple, tous les flux d’E/S standard sont stockés dans les liaisons de niveau supérieur de variables spéciales bien connues. Le flux de sortie standard est stocké dans *standard-output*.

Supposons qu’une fonction foo écrit sur la sortie standard :

( defun foo () ( format t “Hello, world” ))

Pour capturer sa sortie dans une chaîne de caractères, *standard-output* peut être lié à un flux de chaîne et appelé :

( with-output-to-string ( *standard-output* ) ( foo )) -> “Bonjour, monde” ; sortie collectée renvoyée sous forme de chaîne Lexical

Common Lisp prend en charge les environnements lexicaux. Formellement, les liaisons dans un environnement lexical ont une portée lexicale et peuvent avoir soit une étendue indéfinie, soit une étendue dynamique, selon le type d’espace de noms. La portée lexicale signifie que la visibilité est physiquement limitée au bloc dans lequel la liaison est établie. Les références qui ne sont pas insérées textuellement (c’est-à-dire lexicalement) dans ce bloc ne voient tout simplement pas cette liaison.

Les balises d’un TAGBODY ont une portée lexicale. L’expression (GO X) est erronée si elle n’est pas imbriquée dans un TAGBODY qui contient une étiquette X. Cependant, les liaisons d’étiquettes disparaissent lorsque le TAGBODY termine son exécution, car elles ont une étendue dynamique. Si ce bloc de code est ressaisi par l’invocation d’une fermeture lexicale , il est invalide pour le corps de cette fermeture d’essayer de transférer le contrôle à une balise via GO :

( defvar *caché* ) ;; occupera une fonction ( tagbody ( setf *stashed* ( lambda () ( go some-label ))) ( go end-label ) ;; sauter le (print “Hello”) some-label ( print “Hello” ) end-label ) -> NÉANT

Lorsque le TAGBODY est exécuté, il évalue d’abord la forme setf qui stocke une fonction dans la variable spéciale *stashed*. Ensuite, le (go end-label) transfère le contrôle à end-label, en sautant le code (print “Hello”). Puisque end-label est à la fin du tagbody, le tagbody se termine, donnant NIL. Supposons que la fonction précédemment mémorisée soit maintenant appelée :

( funcall *caché* ) ;; Erreur!

Cette situation est erronée. La réponse d’une implémentation est une condition d’erreur contenant le message “GO : le corps de la balise pour la balise SOME-LABEL a déjà été laissé”. La fonction a essayé d’évaluer (go some-label), qui est lexicalement intégré dans le tagbody, et se résout en label. Cependant, le corps de balise ne s’exécute pas (son étendue est terminée) et le transfert de contrôle ne peut donc pas avoir lieu.

Les liaisons de fonctions locales dans Lisp ont une portée lexicale et les liaisons de variables ont également une portée lexicale par défaut. Contrairement aux labels GO, les deux ont une portée indéfinie. Lorsqu’une fonction lexicale ou une liaison de variable est établie, cette liaison continue d’exister aussi longtemps que des références à celle-ci sont possibles, même après la fin de la construction qui a établi cette liaison. Les références aux variables et fonctions lexicales après la terminaison de leur construction d’établissement sont possibles grâce aux fermetures lexicales .

La liaison lexicale est le mode de liaison par défaut pour les variables Common Lisp. Pour un symbole individuel, il peut être basculé en portée dynamique, soit par une déclaration locale, soit par une déclaration globale. Ce dernier peut se produire implicitement via l’utilisation d’une construction comme DEFVAR ou DEFPARAMETER. C’est une convention importante dans la programmation Common Lisp que les variables spéciales (c’est-à-dire à portée dynamique) ont des noms qui commencent et se terminent par un astérisque sigil * dans ce qu’on appelle la ” convention antibruit “. [17] Si elle est respectée, cette convention crée effectivement un espace de noms séparé pour les variables spéciales, de sorte que les variables destinées à être lexicales ne soient pas accidentellement rendues spéciales.

La portée lexicale est utile pour plusieurs raisons.

Premièrement, les références aux variables et aux fonctions peuvent être compilées en un code machine efficace, car la structure de l’environnement d’exécution est relativement simple. Dans de nombreux cas, il peut être optimisé pour empiler le stockage, de sorte que l’ouverture et la fermeture de portées lexicales ont une surcharge minimale. Même dans les cas où des fermetures complètes doivent être générées, l’accès à l’environnement de la fermeture reste efficace ; généralement, chaque variable devient un décalage dans un vecteur de liaisons, et ainsi une référence de variable devient une simple instruction de chargement ou de stockage avec un mode d’adressage base plus décalage .

Deuxièmement, la portée lexicale (combinée à une étendue indéfinie) donne lieu à la fermeture lexicale , qui à son tour crée tout un paradigme de programmation centré sur l’utilisation des fonctions comme objets de première classe, qui est à la base de la programmation fonctionnelle.

Troisièmement, peut-être le plus important, même si les fermetures lexicales ne sont pas exploitées, l’utilisation de la portée lexicale isole les modules de programme des interactions indésirables. Du fait de leur visibilité restreinte, les variables lexicales sont privées. Si un module A lie une variable lexicale X et appelle un autre module B, les références à X dans B ne se résoudront pas accidentellement en X lié dans A. B n’a tout simplement pas accès à X. Pour les situations dans lesquelles des interactions disciplinées à travers une variable sont souhaitable, Common Lisp fournit des variables spéciales. Les variables spéciales permettent à un module A d’établir une liaison pour une variable X qui est visible par un autre module B, appelé depuis A. Pouvoir faire cela est un avantage, et pouvoir empêcher que cela se produise est également un avantage ; par conséquent, Common Lisp prend en charge à la fois la portée lexicale et dynamique .

Macros

Une macro en Lisp ressemble superficiellement à une fonction en cours d’utilisation. Cependant, plutôt que de représenter une expression qui est évaluée, il représente une transformation du code source du programme. La macro obtient la source qu’elle entoure en tant qu’arguments, les lie à ses paramètres et calcule une nouvelle forme source. Ce nouveau formulaire peut également utiliser une macro. L’expansion de la macro est répétée jusqu’à ce que le nouveau formulaire source n’utilise plus de macro. La forme calculée finale est le code source exécuté au moment de l’exécution.

Utilisations typiques des macros en Lisp :

  • nouvelles structures de contrôle (exemple : constructions en boucle, constructions en branchement)
  • constructions de portée et de liaison
  • syntaxe simplifiée pour le code source complexe et répété
  • formulaires de définition de niveau supérieur avec effets secondaires au moment de la compilation
  • programmation pilotée par les données
  • langages embarqués spécifiques à un domaine (exemples : SQL , HTML , Prolog )
  • formulaires de finalisation implicite

Diverses fonctionnalités standard de Common Lisp doivent également être implémentées sous forme de macros, telles que :

  • l’abstraction standard setf, pour permettre des extensions personnalisées au moment de la compilation des opérateurs d’affectation/d’accès
  • with-accessors, with-slots, with-open-fileet autres WITHmacros similaires
  • Selon l’implémentation, ifou condest une macro construite sur l’autre, l’opérateur spécial ; whenet unlessse composent de macros
  • Le puissant looplangage spécifique à un domaine

Les macros sont définies par la macro defmacro . L’opérateur spécial macrolet permet la définition de macros locales (de portée lexicale). Il est également possible de définir des macros pour les symboles en utilisant define-symbol-macro et symbol-macrolet .

Le livre de Paul Graham On Lisp décrit en détail l’utilisation des macros dans Common Lisp. Le livre de Doug Hoyte Let Over Lambda étend la discussion sur les macros, affirmant que “les macros sont le plus grand avantage de Lisp en tant que langage de programmation et le plus grand avantage de tout langage de programmation”. Hoyte fournit plusieurs exemples de développement itératif de macros.

Exemple d’utilisation d’une macro pour définir une nouvelle structure de contrôle

Les macros permettent aux programmeurs Lisp de créer de nouvelles formes syntaxiques dans le langage. Une utilisation typique consiste à créer de nouvelles structures de contrôle. L’exemple de macro fournit une untilconstruction en boucle. La syntaxe est :

(jusqu’au formulaire de test*)

La définition de macro pour jusqu’à :

( defmacro jusqu’à ( test &body body ) ( let (( start-tag ( gensym “START” )) ( end-tag ( gensym “END” ))) ` ( tagbody , start-tag ( when , test ( go , end- balise )) ( progn ,@ body ) ( aller , balise de début ) , balise de fin )))

tagbody est un opérateur spécial Common Lisp primitif qui permet de nommer des balises et d’utiliser le formulaire go pour accéder à ces balises. Le backquote ` fournit une notation qui fournit des modèles de code, où la valeur des formulaires précédés d’une virgule est remplie. Les formulaires précédés d’une virgule et d’un arobase sont intégrés. Le formulaire tagbody teste la condition de fin. Si la condition est vraie, il saute à la balise de fin. Sinon, le code de corps fourni est exécuté, puis il saute à la balise de début.

Un exemple d’utilisation de la macro jusqu’à ci-dessus :

( jusqu’à ( = ( random 10 ) 0 ) ( write-line “Hello” ))

Le code peut être étendu à l’aide de la fonction macroexpand-1 . L’extension de l’exemple ci-dessus ressemble à ceci :

( TAGBODY #:START1136 ( WHEN ( ZEROP ( RANDOM 10 )) ( GO #:END1137 )) ( PROGN ( WRITE-LINE “hello” )) ( GO #:START1136 ) #:END1137 )

Lors de l’expansion de la macro, la valeur de la variable test est (= (random 10) 0) et la valeur du corps de la variable est ((write-line “Hello”)) . Le corps est une liste de formulaires.

Les symboles sont généralement automatiquement mis en majuscule. L’extension utilise le TAGBODY avec deux étiquettes. Les symboles de ces étiquettes sont calculés par GENSYM et ne sont intégrés dans aucun package. Deux formulaires go utilisent ces balises pour sauter. Étant donné que tagbody est un opérateur primitif dans Common Lisp (et non une macro), il ne sera pas étendu à autre chose. Le formulaire développé utilise la macro when , qui sera également développée. L’expansion complète d’un formulaire source s’appelle le code walking .

Dans la forme complètement développée ( walkée ), la forme when est remplacée par la primitive if :

( TAGBODY #:START1136 ( IF ( ZEROP ( RANDOM 10 )) ( PROGN ( GO #:END1137 )) NIL ) ( PROGN ( WRITE-LINE “hello” )) ( GO #:START1136 )) #:END1137 )

Toutes les macros doivent être développées avant que le code source qui les contient puisse être évalué ou compilé normalement. Les macros peuvent être considérées comme des fonctions qui acceptent et renvoient des expressions S – similaires aux arbres de syntaxe abstraite , mais sans s’y limiter. Ces fonctions sont appelées avant l’évaluateur ou le compilateur pour produire le code source final. Les macros sont écrites en Common Lisp normal et peuvent utiliser n’importe quel opérateur Common Lisp (ou tiers) disponible.

Capture et ombrage variables

Les macros Common Lisp sont capables de ce que l’on appelle communément la capture de variables , où les symboles dans le corps de la macro-expansion coïncident avec ceux du contexte d’appel, permettant au programmeur de créer des macros dans lesquelles divers symboles ont une signification particulière. Le terme capture de variable est quelque peu trompeur, car tous les Espaces de noms sont vulnérables à la capture indésirable, y compris l’espace de noms d’opérateur et de fonction, l’espace de noms d’étiquette de corps de balise, la balise catch, le gestionnaire de condition et les Espaces de noms de redémarrage.

La capture variable peut introduire des défauts logiciels. Cela se produit de l’une des deux manières suivantes :

  • De la première manière, une expansion de macro peut créer par inadvertance une référence symbolique que l’auteur de la macro suppose qu’elle résoudra dans un espace de noms global, mais le code dans lequel la macro est développée se trouve fournir une définition locale et masquée qui vole cette référence. Appelons cela la capture de type 1.
  • La deuxième méthode, la capture de type 2, est tout le contraire : certains des arguments de la macro sont des morceaux de code fournis par l’appelant de la macro, et ces morceaux de code sont écrits de telle sorte qu’ils font référence aux liaisons environnantes. Cependant, la macro insère ces morceaux de code dans une extension qui définit ses propres liaisons qui capturent accidentellement certaines de ces références.

Le dialecte Scheme de Lisp fournit un système de macro-écriture qui fournit la transparence référentielle qui élimine les deux types de problème de capture. Ce type de macro système est parfois appelé “hygiénique”, notamment par ses promoteurs (qui considèrent les macro systèmes qui ne résolvent pas automatiquement ce problème comme non hygiéniques). [ citation nécessaire ]

Dans Common Lisp, la macro-hygiène est assurée de deux manières différentes.

Une approche consiste à utiliser des gensyms : des symboles uniques garantis qui peuvent être utilisés dans une macro-expansion sans menace de capture. L’utilisation de gensyms dans une définition de macro est une corvée manuelle, mais des macros peuvent être écrites pour simplifier l’instanciation et l’utilisation des gensyms. Les Gensyms résolvent facilement la capture de type 2, mais ils ne s’appliquent pas de la même manière à la capture de type 1, car l’extension de macro ne peut pas renommer les symboles interférents dans le code environnant qui capturent ses références. Gensyms pourrait être utilisé pour fournir des alias stables pour les symboles globaux dont l’expansion macro a besoin. L’expansion de la macro utiliserait ces alias secrets plutôt que les noms bien connus, de sorte que la redéfinition des noms bien connus n’aurait aucun effet néfaste sur la macro.

Une autre approche consiste à utiliser des packages. Une macro définie dans son propre package peut simplement utiliser des symboles internes dans ce package dans son expansion. L’utilisation de forfaits concerne les captures de type 1 et de type 2.

Cependant, les packages ne résolvent pas la capture de type 1 des références aux fonctions et opérateurs Common Lisp standard. La raison en est que l’utilisation de packages pour résoudre les problèmes de capture tourne autour de l’utilisation de symboles privés (symboles dans un package, qui ne sont pas importés ou autrement rendus visibles dans d’autres packages). Alors que les symboles de la bibliothèque Common Lisp sont externes et fréquemment importés ou rendus visibles dans des packages définis par l’utilisateur.

Voici un exemple de capture indésirable dans l’espace de noms de l’opérateur, se produisant lors de l’expansion d’une macro :

;; l’expansion de UNTIL utilise librement DO ( defmacro until ( expression &body body ) ` ( do () ( , expression ) ,@ body )) ;; macrolet établit une liaison d’opérateur lexical pour DO ( macrolet (( do ( … ) … quelque chose d’autre … )) ( jusqu’à ( = ( random 10 ) 0 ) ( write-line “Hello” )))

La untilmacro se développera dans une forme qui appelle doce qui est destiné à faire référence à la macro standard Common Lisp do. Cependant, dans ce contexte, dopeut avoir une signification complètement différente, donc untilpeut ne pas fonctionner correctement.

Common Lisp résout le problème du shadowing des opérateurs et fonctions standards en interdisant leur redéfinition. Parce qu’il redéfinit l’opérateur standard do, le précédent est en fait un fragment de Common Lisp non conforme, ce qui permet aux implémentations de le diagnostiquer et de le rejeter.

Système de conditions

Le système de conditions est responsable de la gestion des exceptions dans Common Lisp. [18] Il fournit des conditions , des gestionnaires et des redémarrages . Les conditions sont des objets décrivant une situation exceptionnelle (par exemple une erreur). Si une condition est signalée, le système Common Lisp recherche un gestionnaire pour ce type de condition et appelle le gestionnaire. Le gestionnairepeut désormais rechercher des redémarrages et utiliser l’un de ces redémarrages pour réparer automatiquement le problème actuel, en utilisant des informations telles que le type de condition et toute information pertinente fournie dans le cadre de l’objet de condition, et appeler la fonction de redémarrage appropriée.

Ces redémarrages, s’ils ne sont pas gérés par du code, peuvent être présentés aux utilisateurs (dans le cadre d’une interface utilisateur, celle d’un débogueur par exemple), afin que l’utilisateur puisse sélectionner et invoquer l’un des redémarrages disponibles. Étant donné que le gestionnaire de condition est appelé dans le contexte de l’erreur (sans dérouler la pile), une récupération complète de l’erreur est possible dans de nombreux cas, où d’autres systèmes de gestion des exceptions auraient déjà terminé la routine en cours. Le débogueur lui-même peut également être personnalisé ou remplacé à l’aide de la *debugger-hook*variable dynamique. Le code trouvé dans les formulaires de déroulement et de protection tels que les finaliseurs sera également exécuté le cas échéant malgré l’exception.

Dans l’exemple suivant (en utilisant Symbolics Genera ), l’utilisateur essaie d’ouvrir un fichier dans un test de fonction Lisp appelé à partir de Read-Eval-Print-LOOP ( REPL ), alors que le fichier n’existe pas. Le système Lisp présente quatre redémarrages. L’utilisateur sélectionne Retry OPEN en utilisant un chemin d’accès différent restart et entre un chemin d’accès différent (lispm-init.lisp au lieu de lispm-int.lisp). Le code utilisateur ne contient aucun code de gestion des erreurs. L’ensemble du code de gestion des erreurs et de redémarrage est fourni par le système Lisp, qui peut gérer et réparer l’erreur sans terminer le code utilisateur.

Commande : (testez “>zippy>lispm-int.lisp”) Erreur : Le fichier est introuvable. Pour lispm :>zippy>lispm-int.lisp.newest LMFS : OUVERT-LOCAL-LMFS-1 Arg 0 : #P”lispm :>zippy>lispm-int.lisp.newest” sA, <Resume> : Réessayez OPEN de lispm :>zippy>lispm-int.lisp.newest sB : Réessayez OPEN en utilisant un chemin d’accès différent sC, <Abort> : retour au niveau supérieur Lisp dans un serveur TELNET sD : processus de redémarrage du terminal TELNET -> Réessayez OPEN en utilisant un nom de chemin différent Utilisez quel chemin à la place [default lispm:>zippy>lispm-int.lisp.newest] : lispm :>zippy>lispm-init.lisp.newest …le programme continue

Système d’objets Common Lisp (CLOS)

Common Lisp comprend une boîte à outils pour la programmation orientée objet , le Common Lisp Object system ou CLOS . Peter Norvig explique combien de Design Patterns sont plus simples à implémenter dans un langage dynamique avec les fonctionnalités de CLOS (Multiple Inheritance, Mixins, Multimethods, Metaclasses, Method combinations, etc.). [19] Plusieurs extensions de Common Lisp pour la programmation orientée objet ont été proposées pour être incluses dans la norme ANSI Common Lisp, mais finalement CLOS a été adopté comme système objet standard pour Common Lisp. CLOS est un système d’objets dynamiques avec répartition multiple et héritage multiple, et diffère radicalement des fonctionnalités POO trouvées dans les langages statiques tels que C++ ou Java . En tant que système d’objets dynamiques, CLOS permet de modifier au moment de l’exécution les fonctions et les classes génériques. Des méthodes peuvent être ajoutées et supprimées, des classes peuvent être ajoutées et redéfinies, des objets peuvent être mis à jour pour les changements de classe et la classe des objets peut être modifiée.

CLOS a été intégré dans ANSI Common Lisp. Les fonctions génériques peuvent être utilisées comme des fonctions normales et constituent un type de données de première classe. Chaque classe CLOS est intégrée dans le système de type Common Lisp. De nombreux types Common Lisp ont une classe correspondante. Il y a plus d’utilisation potentielle de CLOS pour Common Lisp. La spécification ne précise pas si les conditions sont implémentées avec CLOS. Les noms de chemin et les flux pourraient être mis en œuvre avec CLOS. Ces autres possibilités d’utilisation de CLOS pour ANSI Common Lisp ne font pas partie de la norme. Les implémentations réelles de Common Lisp utilisent CLOS pour les noms de chemin, les flux, les entrées-sorties, les conditions, l’implémentation de CLOS lui-même et plus encore.

Compilateur et interpréteur

Un interpréteur Lisp exécute directement le code source Lisp fourni sous forme d’objets Lisp (listes, symboles, nombres, …) lus à partir de s-expressions. Un compilateur Lisp génère du bytecode ou du code machine à partir du code source Lisp. Common Lisp permet à la fois de compiler des fonctions Lisp individuelles en mémoire et de compiler des fichiers entiers en code compilé stocké en externe ( fichiers fasl ).

Plusieurs implémentations de dialectes Lisp antérieurs fournissaient à la fois un interpréteur et un compilateur. Malheureusement, la sémantique était souvent différente. Ces premiers Lisps implémentaient la portée lexicale dans le compilateur et la portée dynamique dans l’interpréteur. Common Lisp exige que l’interpréteur et le compilateur utilisent la portée lexicale par défaut. La norme Common Lisp décrit à la fois la sémantique de l’interpréteur et d’un compilateur. Le compilateur peut être appelé à l’aide de la fonction compile pour les fonctions individuelles et à l’aide de la fonction compile-file pour les fichiers. Common Lisp autorise les déclarations de type et fournit des moyens d’influencer la politique de génération de code du compilateur. Pour ces dernières, différentes qualités d’optimisation peuvent être valorisées entre 0 (pas important) et 3 (le plus important) : vitesse, espace , sécurité , débogage et vitesse de compilation .

Il existe également une fonction pour évaluer le code Lisp : eval. evalprend le code sous forme d’expressions s pré-parsées et non, comme dans d’autres langages, sous forme de chaînes de texte. De cette façon, le code peut être construit avec les fonctions Lisp habituelles pour construire des listes et des symboles, puis ce code peut être évalué avec la fonction eval. Plusieurs implémentations Common Lisp (comme Clozure CL et SBCL) sont implémentées evalà l’aide de leur compilateur. De cette façon, le code est compilé, même s’il est évalué à l’aide de la fonction eval.

Le compilateur de fichiers est appelé à l’aide de la fonction compile-file . Le fichier généré avec le code compilé est appelé un fichier fasl (de fast load ). Ces fichiers fasl ainsi que les fichiers de code source peuvent être chargés avec la fonction load dans un système Common Lisp en cours d’exécution. Selon l’implémentation, le compilateur de fichiers génère du byte-code (par exemple pour la machine virtuelle Java ), du code en langage C (qui est ensuite compilé avec un compilateur C) ou, directement, du code natif.

Les implémentations Common Lisp peuvent être utilisées de manière interactive, même si le code est entièrement compilé. L’idée d’un langage interprété ne s’applique donc pas au Common Lisp interactif.

Le langage fait une distinction entre le temps de lecture, le temps de compilation, le temps de chargement et le temps d’exécution, et permet au code utilisateur de faire également cette distinction pour effectuer le type de traitement souhaité à l’étape souhaitée.

Certains opérateurs spéciaux sont fournis pour s’adapter particulièrement au développement interactif ; par exemple, defvarn’affectera une valeur à sa variable fournie que si elle n’était pas déjà liée, alors defparameterqu’il effectuera toujours l’affectation. Cette distinction est utile lors de l’évaluation, de la compilation et du chargement de code de manière interactive dans une image en direct.

Certaines fonctionnalités sont également fournies pour aider à écrire des compilateurs et des interpréteurs. Les symboles sont constitués d’objets de premier niveau et sont directement manipulables par le code utilisateur. L’ progvopérateur spécial permet de créer des liaisons lexicales par programmation, tandis que les packages sont également manipulables. Le compilateur Lisp est disponible au moment de l’exécution pour compiler des fichiers ou des fonctions individuelles. Ceux-ci facilitent l’utilisation de Lisp comme compilateur ou interpréteur intermédiaire pour un autre langage.

Exemples de codes

Paradoxe de l’anniversaire

Le programme suivant calcule le plus petit nombre de personnes dans une pièce pour lesquelles la probabilité d’anniversaires uniques est inférieure à 50% (le paradoxe des anniversaires , où pour 1 personne la probabilité est évidemment de 100%, pour 2 elle est de 364/365, etc. ). La réponse est 23.

Par convention, les constantes en Common Lisp sont entourées de caractères +.

( defconstante +année-taille+ 365 ) ( defun anniversaire-paradoxe ( probabilité nombre-de-personnes ) ( let (( nouvelle-probabilité ( * ( / ( – +année-taille+ nombre-de-personnes ) +année-taille+ ) probabilité ))) ( si ( < nouveau -probability 0.5 ) ( 1+ nombre-de-personnes ) ( anniversaire-paradoxe nouvelle-probabilité ( 1+ nombre-de-personnes )))))

Appel de la fonction d’exemple à l’aide de REPL (Read Eval Print Loop) :

CL-USER > (anniversaire-paradoxe 1.0 1) 23

Trier une liste d’objets personne

Nous définissons une classe personet une méthode pour afficher le nom et l’âge d’une personne. Ensuite, nous définissons un groupe de personnes comme une liste d’ personobjets. Ensuite, nous parcourons la liste triée.

( defclass person () (( name :initarg :name :accessor person-name ) ( age :initarg :age :accessor person-age )) ( :documentation “The class PERSON with slots NAME and AGE.” )) ( defmethod display (( object person ) stream ) “Afficher un objet PERSON dans un flux de sortie.” ( with-slots ( name age ) object ( format stream “~a (~a)” name age ))) ( defparameter *group* ( list ( make-instance ‘person :name “Bob” :age 33 ) ( make-instance ‘person :name “Chris” :age 16 ) ( make-instance ‘person :name “Ash” :age 23 )) “Une liste d’objets PERSON.” ) ( dolist ( person ( sort ( copy-list *group* ) #’ > :key #’ person-age )) ( display person *standard-output* ) ( terpri ))

Il imprime les trois noms avec l’âge décroissant.

Bob (33) Frêne (23) Chris (16)

Exponentielle par élévation au carré

L’utilisation de la macro LOOP est illustrée :

( defun power ( x n ) ( loop with result = 1 while ( plusp n ) when ( oddp n ) do ( setf result ( * result x )) do ( setf x ( * x x ) n ( tronquer n 2 )) enfin ( résultat renvoyé )))

Exemple d’utilisation :

CL-USER > (puissance 2 200) 1606938044258990275541962092341162602522202993782792835301376

Comparez avec l’exponentiation intégrée :

CL-USER > (= (expt 2 200) (puissance 2 200)) J

Retrouvez la liste des coquillages disponibles

WITH-OPEN-FILE est une macro qui ouvre un fichier et fournit un flux. Au retour du formulaire, le dossier est automatiquement fermé. FUNCALL appelle un objet fonction. La BOUCLE collecte toutes les lignes qui correspondent au prédicat.

( defun list-matching-lines ( file predicate ) “Renvoie une liste de lignes dans file, pour lesquelles le prédicat appliqué à la ligne renvoie T.” ( with-open-file ( stream file ) ( loop for line = ( read- line stream nil nil ) while line when ( funcall predicate line ) collect it )))

La fonction AVAILABLE-SHELLS appelle la fonction ci-dessus LIST-MATCHING-LINES avec un nom de chemin et une fonction anonyme comme prédicat. Le prédicat renvoie le chemin d’accès d’un shell ou NIL (si la chaîne n’est pas le nom de fichier d’un shell).

( defun available-shells ( &optional ( file #p”/etc/shells” )) ( list-matching-lines file ( lambda ( line ) ( and ( plusp ( length line )) ( char= ( char line 0 ) # / ) ( chemin d’accès ( string-right-trim ‘ ( #space #tab ) line ))))))

Exemples de résultats (sur Mac OS X 10.6) :

CL-USER > ( available-shells ) ( #P”/bin/bash” #P”/bin/csh” #P”/bin/ksh” #P”/bin/sh” #P”/bin/tcsh” #P”/bin/zsh” )

Comparaison avec d’autres Lisps

Common Lisp est le plus souvent comparé et opposé à Scheme , ne serait-ce que parce qu’il s’agit des deux dialectes Lisp les plus populaires. Scheme est antérieur à CL et provient non seulement de la même tradition Lisp, mais de certains des mêmes ingénieurs – Guy L. Steele , avec qui Gerald Jay Sussman a conçu Scheme, a présidé le comité des normes pour Common Lisp.

Common Lisp est un langage de programmation à usage général, contrairement aux variantes Lisp telles que Emacs Lisp et AutoLisp qui sont des langages d’extension intégrés dans des produits particuliers (GNU Emacs et AutoCAD, respectivement). Contrairement à de nombreux Lisp antérieurs, Common Lisp (comme Scheme ) utilise par défaut la portée des variables lexicales pour le code interprété et compilé.

La plupart des systèmes Lisp dont les conceptions ont contribué à Common Lisp – tels que ZetaLisp et Franz Lisp – utilisaient des variables à portée dynamique dans leurs interpréteurs et des variables à portée lexicale dans leurs compilateurs. Scheme a introduit la seule utilisation de variables à portée lexicale dans Lisp ; une inspiration d’ ALGOL 68 . CL prend également en charge les variables à portée dynamique, mais elles doivent être explicitement déclarées comme “spéciales”. Il n’y a aucune différence de portée entre les interpréteurs ANSI CL et les compilateurs.

Common Lisp est parfois appelé Lisp-2 et Scheme a Lisp-1 , faisant référence à l’utilisation par CL d’Espaces de noms séparés pour les fonctions et les variables. (En fait, CL possède de nombreux Espaces de noms, tels que ceux des balises go, des noms de blocs et des mots- loopclés). Il existe une controverse de longue date entre les défenseurs de CL et de Scheme sur les compromis impliqués dans plusieurs Espaces de noms. Dans Scheme, il faut (en gros) éviter de donner des noms de variables qui entrent en conflit avec les fonctions ; Les fonctions de schéma ont fréquemment des arguments nommés lis, lstou lystafin de ne pas entrer en conflit avec la fonction systèmelist. Cependant, en CL, il est nécessaire de se référer explicitement à l’espace de noms de la fonction lors du passage d’une fonction en tant qu’argument, ce qui est également courant, comme dans l’ sortexemple ci-dessus.

CL diffère également de Scheme dans sa gestion des valeurs booléennes. Scheme utilise les valeurs spéciales #t et #f pour représenter la vérité et la fausseté. CL suit l’ancienne convention Lisp consistant à utiliser les symboles T et NIL, NIL représentant également la liste vide. Dans CL, toute valeur non NIL est traitée comme vraie par les conditions, telles que if, alors que dans Scheme, toutes les valeurs non #f sont traitées comme vraies. Ces conventions permettent à certains opérateurs dans les deux langages de servir à la fois de prédicats (répondre à une question booléenne) et de renvoyer une valeur utile pour un calcul ultérieur, mais dans Scheme la valeur ‘() qui équivaut à NIL en Common Lisp est évaluée à true dans une expression booléenne.

Enfin, les documents de normes Scheme nécessitent une optimisation des appels de queue , ce que la norme CL ne fait pas. La plupart des implémentations CL offrent une optimisation des appels terminaux, bien que souvent uniquement lorsque le programmeur utilise une directive d’optimisation. Néanmoins, le style de codage CL commun ne favorise pas l’utilisation omniprésente de la récursivité que le style Scheme préfère – ce qu’un programmeur Scheme exprimerait avec la récursivité de queue, un utilisateur CL exprimerait généralement avec une expression itérative dans do, dolist, loop, ou (plus récemment) avec le iterateemballer.

Implémentations

Voir la catégorie Implémentations Common Lisp .

Common Lisp est défini par une spécification (comme Ada et C ) plutôt que par une implémentation (comme Perl ). Il existe de nombreuses implémentations, et les domaines de détails standard dans lesquels elles peuvent valablement différer.

De plus, les implémentations ont tendance à être accompagnées d’extensions, qui fournissent des fonctionnalités non couvertes par la norme :

  • Niveau supérieur interactif (REPL)
  • Collecte des ordures
  • Débogueur, Stepper et Inspecteur
  • Structures de données faibles (tables de hachage)
  • Séquences extensibles
  • BOUCLE extensible
  • Accès à l’environnement
  • Protocole de méta-objet CLOS
  • Flux extensibles basés sur CLOS
  • Système de condition basé sur CLOS
  • Flux réseau
  • CLOS persistant
  • Prise en charge d’Unicode
  • Interface en langue étrangère (souvent vers C)
  • Interface du système d’exploitation
  • InterfaceJava
  • Threads et multitraitement
  • Livraison d’applications (applications, bibliothèques dynamiques)
  • Sauvegarde des images

Des bibliothèques de logiciels libres et open source ont été créées pour prendre en charge les extensions de Common Lisp de manière portable, et se trouvent notamment dans les référentiels de Common-Lisp.net [20] et CLOCC (Common Lisp Open Code Collection) [21 ] projets.

Les implémentations Common Lisp peuvent utiliser n’importe quel mélange de compilation de code natif, de compilation ou d’interprétation de code d’octet. Common Lisp a été conçu pour prendre en charge les compilateurs incrémentiels , les compilateurs de fichiers et les compilateurs de blocs. Des déclarations standard pour optimiser la compilation (comme l’inlining de fonction ou la spécialisation de type) sont proposées dans la spécification du langage. La plupart des implémentations Common Lisp compilent le code source en code machine natif . Certaines implémentations peuvent créer des applications autonomes (optimisées). D’autres compilent en bytecode interprété, qui est moins efficace que le code natif, mais facilite la portabilité du code binaire. Certains compilateurs compilent le code Common Lisp en code C. L’idée fausse selon laquelle Lisp est un langage purement interprété est probablement due au fait que les environnements Lisp fournissent une invite interactive et que le code est compilé un par un, de manière incrémentielle. Avec Common Lisp, la compilation incrémentale est largement utilisée.

Certaines implémentations basées sur Unix ( CLISP , SBCL ) peuvent être utilisées comme langage de script ; c’est-à-dire invoqué par le système de manière transparente à la manière d’un interpréteur de shell Perl ou Unix . [22]

Liste des implémentations

Implémentations commerciales Allegro Common Lisp pour Microsoft Windows, FreeBSD, Linux, Apple macOS et diverses variantes UNIX. Allegro CL fournit un environnement de développement intégré (IDE) (pour Windows et Linux) et des capacités étendues pour la livraison d’applications. Lisp commun liquide anciennement appelé Lucid Common Lisp . Maintenance uniquement, pas de nouvelles versions. LispWorks pour Microsoft Windows, FreeBSD, Linux, Apple macOS, iOS, Android et diverses variantes UNIX. LispWorks fournit un environnement de développement intégré (IDE) (disponible pour la plupart des plates-formes, mais pas pour iOS et Android) et des fonctionnalités étendues pour la livraison d’applications. mocl pour iOS, Android et macOS. Genres ouverts pour DEC Alpha. Scieneer Common Lisp qui est conçu pour le calcul scientifique de haute performance. Implémentations librement redistribuables Ours armé Common Lisp (ABCL) Une implémentation CL qui s’exécute sur la machine virtuelle Java . [23] Il inclut un compilateur de byte code Java et permet l’accès aux bibliothèques Java depuis CL. Ce n’était auparavant qu’un composant de l’ éditeur Armed Bear J. CLIP Une implémentation de compilation de bytecode, portable et qui s’exécute sur plusieurs systèmes Unix et de type Unix (y compris macOS ), ainsi que sur Microsoft Windows et plusieurs autres systèmes. Clôture CL (CCL) À l’ origine, un fork gratuit et open-source de Macintosh Common Lisp. Comme cette histoire l’indique, CCL a été écrit pour le Macintosh, mais Clozure CL fonctionne maintenant sur macOS , FreeBSD , Linux , Solaris et Windows . Les ports x86 32 et 64 bits sont pris en charge sur chaque plate-forme. De plus, il existe des ports Power PC pour Mac OS et Linux. CCL était auparavant connu sous le nom d’OpenMCL, mais ce nom n’est plus utilisé, pour éviter toute confusion avec la version open source de Macintosh Common Lisp. CMUCL Originaire de l’Université Carnegie Mellon , maintenant maintenu en tant que logiciel libre et open-source par un groupe de bénévoles. CMUCL utilise un compilateur de code natif rapide. Il est disponible sur Linux et BSD pour Intel x86 ; Linux pour Alpha ; macOS pour Intel x86 et PowerPC ; et Solaris, IRIX et HP-UX sur leurs plates-formes natives. Corman Common Lisp pour Microsoft Windows. En janvier 2015, Corman Lisp a été publié sous licence MIT. [24] Lisp commun intégrable (ECL) ECL inclut un interpréteur et un compilateur de bytecode. Il peut également compiler du code Lisp en code machine via un compilateur C. ECL compile ensuite le code Lisp en C, compile le code C avec un compilateur C et peut ensuite charger le code machine résultant. Il est également possible d’intégrer ECL dans des programmes C et du code C dans des programmes Common Lisp. GNU Common Lisp (GCL) Le compilateur Lisp du projet GNU . Pas encore entièrement conforme à la norme ANSI, GCL est cependant l’implémentation de choix pour plusieurs grands projets, notamment les outils mathématiques Maxima , AXIOM et (historiquement) ACL2 . GCL fonctionne sous Linux sous onze architectures différentes, ainsi que sous Windows, Solaris et FreeBSD . Macintosh Common Lisp (MCL) La version 5.2 pour les ordinateurs Apple Macintosh avec un processeur PowerPC exécutant Mac OS X est open source. RMCL (basé sur MCL 5.2) s’exécute sur des ordinateurs Apple Macintosh basés sur Intel à l’aide du traducteur binaire Rosetta d’Apple. Lisp commun ManKai (MKCL) Une filiale d’ ECL . MKCL met l’accent sur la fiabilité, la stabilité et la qualité globale du code grâce à un système d’exécution fortement retravaillé et nativement multithread. Sous Linux, MKCL dispose d’un système d’exécution entièrement compatible POSIX. Movitz Implémente un environnement Lisp pour les ordinateurs x86 sans s’appuyer sur un système d’exploitation sous-jacent. Poplog Poplog implémente une version de CL, avec POP-11 , et éventuellement Prolog , et Standard ML (SML), permettant une programmation en langage mixte. Pour tous, le langage d’implémentation est POP-11, qui est compilé de manière incrémentale. Il dispose également d’un éditeur de type Emacs intégré qui communique avec le compilateur. Lisp commun de Steel Bank (SBCL) Une filiale de la CMUCL . “D’une manière générale, SBCL se distingue de CMU CL par une plus grande emphase sur la maintenabilité.” [25] SBCL fonctionne sur les plates-formes CMUCL, à l’exception de HP/UX ; en outre, il fonctionne sous Linux pour AMD64, PowerPC, SPARC, MIPS, Windows x86 [26] et dispose d’un support expérimental pour fonctionner sous Windows AMD64. SBCL n’utilise pas d’interpréteur par défaut ; toutes les expressions sont compilées en code natif à moins que l’utilisateur n’active l’interpréteur. Le compilateur SBCL génère du code natif rapide selon une version précédente de The Computer Language Benchmarks Game . [27] Ufasoft Common Lisp port de CLISP pour la plate-forme Windows avec un noyau écrit en C++. Autres implémentations

Apprendre encore plus Cette section a besoin de citations supplémentaires pour vérification . ( juillet 2018 ) Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed. (Learn how and when to remove this template message)

Austin Kyoto Common Lisp une évolution de Kyoto Common Lisp par Bill Schelter Papillon commun Lisp une implémentation écrite dans Scheme pour l’ ordinateur multiprocesseur BBN Butterfly [28] [29] CLIC un compilateur Common Lisp vers C [30] CLOE Common Lisp pour PC par Symbolics Codemist Common Lisp utilisé pour la version commerciale du système de calcul formel Axiom [31] [32] ExperCommon LispComment une première implémentation pour Apple Macintosh par ExperTelligence Lisp commun d’or une implémentation pour le PC par GoldHill Inc. [33] [34] Ibuki Common Lisp une version commercialisée de Kyoto Common Lisp Lisp commun de Kyoto le premier compilateur Common Lisp qui a utilisé C comme langage cible. GCL, ECL et MKCL proviennent de cette implémentation Common Lisp. L une petite version de Common Lisp pour les systèmes embarqués développée par IS Robotics, maintenant iRobot [35] Machines Lisp (de Symbolics , TI [36] [37] et Xerox [38] ) fourni des implémentations de Common Lisp en plus de leur dialecte Lisp natif (Lisp Machine Lisp ou Interlisp). Le CLOS était également disponible. Symbolics fournit une version améliorée de Common Lisp. [39] [40] [41] Procyon Common Lisp une implémentation pour Windows et Mac OS, utilisée par Franz pour leur port Windows d’Allegro CL LISP commun en saphir étoilé une implémentation pour le PC SubL une variante de Common Lisp utilisée pour l’implémentation du système à base de connaissances Cyc [42] Lisp commun de haut niveau une implémentation précoce pour l’exécution simultanée [43] CMT une implémentation de bibliothèque partagée [44] [45] Lisp commun VAX Implémentation de Digital Equipment Corporation exécutée sur des systèmes VAX exécutant VMS ou ULTRIX XLISP une implémentation écrite par David Betz [46]

Applications

Voir aussi : Catégorie : Logiciel Common Lisp (langage de programmation)

Common Lisp est utilisé pour développer des applications de recherche (souvent en Intelligence Artificielle ), pour le développement rapide de prototypes ou pour des applications déployées.

Common Lisp est utilisé dans de nombreuses applications commerciales, y compris Yahoo! Site de commerce en ligne du magasin, qui impliquait à l’origine Paul Graham et a ensuite été réécrit en C ++ et Perl . [47] D’autres exemples notables incluent :

  • ACT-R , une architecture cognitive utilisée dans un grand nombre de projets de recherche.
  • Authorizer’s Assistant , [48] [49] un grand système basé sur des règles utilisé par American Express, analysant les demandes de crédit.
  • Cyc , un projet de longue date visant à créer un système basé sur les connaissances qui fournit une énorme quantité de connaissances de bon sens.
  • Gensym G2 , un système expert temps réel et un moteur de règles métier [50]
  • Genworks GDL, [51] basé sur le noyau Gendl open-source.
  • L’environnement de développement de la série de jeux vidéo Jak et Daxter , développé par Naughty Dog .
  • Le moteur de recherche à bas prix d’ ITA Software , utilisé par des sites Web de voyage tels que Orbitz et Kayak.com et des compagnies aériennes telles qu’American Airlines , Continental Airlines et US Airways .
  • Mirai , une suite graphique 3D. Il a été utilisé pour animer le visage de Gollum dans le film Le Seigneur des Anneaux : Les Deux Tours .
  • Opusmodus est un système de composition musicale basé sur Common Lisp, utilisé dans la composition assistée par ordinateur . [52]
  • Prototype Verification System (PVS), un environnement mécanisé pour la spécification et la vérification formelles.
  • PWGL est un environnement de programmation visuel sophistiqué basé sur Common Lisp, utilisé dans la composition assistée par ordinateur et la synthèse sonore. [53]
  • Piano, une suite complète d’analyse d’avions, écrite en Common Lisp, [54] utilisée par des entreprises comme Boeing , Airbus et Northrop Grumman . [55]
  • Grammarly , une plate-forme d’amélioration de l’écriture en anglais, a son moteur de grammaire principal écrit en Common Lisp. [56]
  • L’ outil d’analyse dynamique et de replanification (DART), qui aurait à lui seul remboursé au cours des années 1991 à 1995 les trente années d’ investissements de la DARPA dans la recherche sur l’IA.
  • de la NASA« Deep Space 1 Lab de la NASA , un programme primé [57] Common Lisp [58] pour le pilotage automatique du vaisseau spatial Deep Space One .
  • SigLab, une plate-forme Common Lisp pour le traitement du signal utilisée dans la défense antimissile, construite par Raytheon . [54]
  • Système de planification de mission Mars Pathfinder de la NASA . [59]
  • SPIKE, un système de programmation pour les observatoires et les satellites terrestres ou spatiaux, notamment le télescope spatial Hubble , [60] écrit en Common Lisp. [61]
  • Common Lisp a été utilisé pour prototyper le ramasse-miettes du Common Language Runtime .NET de Microsoft . [62]
  • La version originale de Reddit , bien que les développeurs soient ensuite passés à Python en raison du manque de bibliothèques pour Common Lisp, selon un article de blog officiel du co-fondateur de Reddit, Steve Huffman . [63]

Il existe également des applications open source écrites en Common Lisp, telles que :

  • LCA2 , un démonstrateur de théorèmes automatisé complet pour une variante applicative de Common Lisp.
  • Axiom , un système sophistiqué de calcul formel .
  • Maxima , un système d’algèbre informatique sophistiqué , basé sur Macsyma.
  • OpenMusic , un environnement de programmation visuel orienté objet basé sur Common Lisp, utilisé dans la composition assistée par ordinateur .
  • Pgloader, [64] un chargeur de données pour PostgreSQL , qui a été réécrit de Python en Common Lisp.[65]
  • Stumpwm , un gestionnaire de fenêtres X11 en mosaïque, piloté par clavier, entièrement écrit en Common Lisp.

Voir également

  • Portail de programmation informatique
  • Common Lisp le langage
  • Sur Lisp
  • Lisp commun pratique

Références

  1. ^ “Action sur les normes ANSI – 28 décembre 2018” (PDF) . ansi.org .
  2. ^ Cité de la couverture de la norme citée. ANSI INCITS 226-1994 [S2008], en vente sur la page de document de la norme Archivé le 27 septembre 2020, à la Wayback Machine .
  3. ^ “CLHS : À propos de Common Lisp HyperSpec (TM)” . lispworks.com .
  4. ^ “CLHS : Section 1.1.2” . lispworks.com .
  5. ^ “Implémentations de Lisp commun : une enquête” . Archivé de l’original le 21 avril 2012 . Récupéré le 22 décembre 2007 .
  6. ^ “Les anciens programmes LISP fonctionnent toujours dans Common Lisp” . Consulté le 13 mai 2015 .
  7. ^ “Racines de” Yu-Shiang Lisp “, Courrier de Jon L White, 1982” . cmu.edu .
  8. ^ “Index de courrier” . cl-su-ai.lisp.se .
  9. ^ Anti-LOOPisme réflexe et autres phénomènes de courrier électronique: modèles oraux, écrits et électroniques dans la communication assistée par ordinateur, JoAnne Yates et Wanda J. Orlikowski., 1993 Archivé le 8 août 2012 à la Wayback Machine
  10. ^ Jr, Steele; L, Guy (15 août 1982). Un aperçu de COMMON LISP . LFP ’82. ACM. p. 98–107. doi : 10.1145/800068.802140 . ISBN 9780897910828. S2CID 14517358 .
  11. ^ Reddy, Abhishek (22 août 2008). “Caractéristiques de Common Lisp” .
  12. ^ “Prise en charge d’Unicode” . Le wiki Common Lisp . Récupéré le 21 août 2008 .
  13. ^ Richard P. Gabriel; Kent M. Pitman (juin 1988). “Problèmes techniques de séparation dans les cellules de fonction et les cellules de valeur” . Lisp et calcul symbolique . 1 (1): 81–101. doi : 10.1007/bf01806178 . S2CID 26716515 .
  14. ^ “Common Lisp Hyperspec: Section 3.1.7” .
  15. ^ “Common Lisp Hyperspec: Fonction PLANCHER” .
  16. ^ “Common Lisp Hyperspec: Accesseur GETHASH” .
  17. ^ “Laissez Lambda” . letoverlambda.com .
  18. ^ Peter Seibel (7 avril 2005). Lisp commun pratique . Apress. ISBN 978-1-59059-239-7.
  19. ^ “Modèles de conception dans la programmation dynamique” . norvig.com .
  20. ^ “Common-Lisp.net” .
  21. ^ “Collection de codes ouverts Common Lisp” .
  22. ^ “32.6. Démarrage rapide de la livraison avec CLISP” . clisp.cons.org .
  23. ^ “Ours armé Common Lisp” .
  24. ^ “Les sources de Corman Lisp sont maintenant disponibles” .
  25. ^ “Histoire et droit d’auteur” . Banque d’acier Common Lisp .
  26. ^ “Table de plate-forme” . Banque d’acier Common Lisp .
  27. ^ “Quels programmes sont les plus rapides ? – Jeu de repères de langage informatique” . 20 mai 2013. Archivé de l’original le 20 mai 2013.
  28. ^ “Paquet : lang/lisp/impl/bbn/” . cs.cmu.edu .
  29. ^ “Développements récents dans Butterfly Lisp, 1987, Actes AAAI” (PDF) . aaai.org .
  30. ^ Burkart, O.; Goerigk, W.; Knutzen, H. (22 juin 1992). “CLICC: Une nouvelle approche de la compilation de programmes Common Lisp en C”. CiteSeerX 10.1.1.38.1282 . {{cite journal}}: Cite journal requires |journal= (help)
  31. ^ “codemist.co.uk” . lisp.codemist.co.uk .
  32. ^ “Axiome, l’horizon de 30 ans, page 43” (PDF) .
  33. ^ “Développeur Golden Common Lisp” . goldhill-inc.com .
  34. ^ Golden Common LISP: Une approche pratique, David J. Steele, juin 2000 par Addison Wesley Publishing Company
  35. ^ Brooks, Rodney A.; al., et (22 juin 1995). “L – Un Lisp commun pour les systèmes embarqués”. CiteSeerX 10.1.1.2.1953 . {{cite journal}}: Cite journal requires |journal= (help)
  36. ^ “Concepts de programmation de l’explorateur TI” (PDF) .
  37. ^ “Référence TI Explorer Lisp” (PDF) .
  38. ^ “Notes de version de Medley Lisp” (PDF) .
  39. ^ “Dictionnaire Lisp symbolique symbolique” (PDF) . trailing-edge.com .
  40. ^ “Concepts symboliques du langage Lisp commun” (PDF) . trailing-edge.com .
  41. ^ “Symbolics Common Lisp Programming Constructs” (PDF) . trailing-edge.com .
  42. ^ “Référence SubL – Cycorp” . cyc.com .
  43. ^ “Top Level Inc. – Groupe de préservation de logiciels” . softwarepreservation.org .
  44. ^ WCL: Fournir des applications Common Lisp efficaces sous Unix , Actes de la conférence ACM de 1992 sur LISP et la programmation fonctionnelle , Pages 260–269
  45. ^ “commonlisp.net :: WCL” . pgc.com . Archivé de l’original le 5 avril 2016 . Consulté le 25 mars 2016 .
  46. ^ “Paquet : lang/lisp/impl/xlisp/” . cs.cmu.edu .
  47. ^ “Battre les moyennes” . paulgraham.com .
  48. ^ “Assistant de l’autorisateur” (PDF) . aaai.org .
  49. ^ Assistant de l’autorisateur American Express Archivé le 12 décembre 2009 à la Wayback Machine
  50. ^ Développement d’applications en temps réel Archivé le 2 août 2016 sur la Wayback Machine . Gensym. Consulté le 16 août 2016.
  51. ^ “Genworks GDL” .
  52. ^ “Opusmodus – Accueil” .
  53. ^ PWGL – Accueil Archivé le 3 mai 2011 à la Wayback Machine , récupéré le 17 juillet 2013.
  54. ^ un b “L’aérospatiale – Lisp Commun” . lisp-lang.org .
  55. ^ “Utilisateurs de piano, extrait de la page du fabricant” .
  56. ^ “Grammarly.com, Exécution de Lisp en production” .
  57. ^ “Agent distant” . ti.arc.nasa.gov .
  58. ^ “Lisping au JPL” .
  59. ^ “Applications client de Franz Inc: NASA” . franz.com .
  60. ^ Système de planification et d’ordonnancement Spike . Stsci.edu. Consulté le 17 juillet 2013.
  61. ^ “Applications de client de Franz Inc : Institut de télescope spatial” . franz.com .
  62. ^ “Comment tout a commencé…AKA la naissance du CLR” . microsoft.com .
  63. ^ Huffman, Steve. “sur lisp” . Vote positif . Archivé de l’original le 17 mai 2018 . Consulté le 11 mai 2019 .
  64. ^ “Pgloader” .
  65. ^ “Pourquoi pgloader est-il tellement plus rapide” .

Bibliographie

Une liste chronologique des livres publiés (ou sur le point d’être publiés) sur Common Lisp (le langage) ou sur la programmation avec Common Lisp (en particulier la programmation IA).

  • Guy L. Steele : Common Lisp the Language, 1ère édition , Digital Press, 1984, ISBN 0-932376-41-X
  • Rodney Allen Brooks : Programmation en Common Lisp , John Wiley and Sons Inc, 1985, ISBN 0-471-81888-7
  • Richard P. Gabriel : Performance et évaluation des systèmes Lisp , The MIT Press, 1985, ISBN 0-262-57193-5 , PDF
  • Robert Wilensky : LISPcraft commun , WW Norton & Co., 1986, ISBN 0-393-95544-3
  • Eugene Charniak , Christopher K. Riesbeck , Drew V. McDermott , James R. Meehan : Programmation d’intelligence artificielle, 2e édition , Lawrence Erlbaum, 1987, ISBN 0-89859-609-2
  • Wendy L. Milner : Common Lisp: A Tutorial , Prentice Hall, 1987, ISBN 0-13-152844-0
  • Deborah G. Tatar : Guide du programmeur sur Common Lisp , Longman Higher Education, 1987, ISBN 0-13-728940-5
  • Taiichi Yuasa , Masami Hagiya : Introduction au Common Lisp , Elsevier Ltd, 1987, ISBN 0-12-774860-1
  • Christian Queinnec , Jérôme Chailloux : Lisp Evolution and Standardization , Ios Pr Inc., 1988, ISBN 90-5199-008-1
  • Taiichi Yuasa , Richard Weyhrauch , Yasuko Kitajima : Common Lisp Drill , Academic Press Inc, 1988, ISBN 0-12-774861-X
  • Wade L. Hennessey : Common Lisp , McGraw-Hill Inc., 1989, ISBN 0-07-028177-7
  • Tony Hasemer , John Dominque : Programmation Lisp commune pour l’intelligence artificielle , Addison-Wesley Educational Publishers Inc, 1989, ISBN 0-201-17579-7
  • Sonya E. Keene : Programmation orientée objet en Common Lisp: Guide du programmeur sur CLOS , Addison-Wesley, 1989, ISBN 0-201-17589-4
  • David Jay Steele : Golden Common Lisp: Une approche pratique , Addison Wesley, 1989, ISBN 0-201-41653-0
  • David S. Touretzky : Lisp commun : une introduction en douceur au calcul symbolique , Benjamin-Cummings, 1989, ISBN 0-8053-0492-4 . Réimpression Web / PDF Douvres (2013) ISBN 978-0486498201
  • Christopher K. Riesbeck , Roger C. Schank : Raisonnement intérieur basé sur des cas , Lawrence Erlbaum, 1989, ISBN 0-89859-767-6
  • Patrick Winston , Berthold Horn : Lisp, 3e édition , Addison-Wesley, 1989, ISBN 0-201-08319-1 , Web
  • Gerard Gazdar , Chris Mellish : Traitement du langage naturel dans LISP : une introduction à la linguistique computationnelle , Addison-Wesley Longman Publishing Co., 1990, ISBN 0-201-17825-7
  • Patrick R. Harrison : Lisp commun et intelligence artificielle , Prentice Hall PTR, 1990, ISBN 0-13-155243-0
  • Timothy Koschmann : Le compagnon Lisp commun , John Wiley & Sons, 1990, ISBN 0-471-50308-8
  • W. Richard Stark : LISP, Lore et Logic , Springer Verlag New York Inc., 1990, ISBN 978-0-387-97072-1 , PDF
  • Molly M. Miller , Eric Benson : Lisp Style & Design , Presse numérique, 1990, ISBN 1-55558-044-0
  • Guy L. Steele : Common Lisp the Language , 2e édition , Digital Press, 1990, ISBN 1-55558-041-6 , Web
  • Robin Jones, Clive Maynard , Ian Stewart : L’art de la programmation Lisp , Springer Verlag New York Inc., 1990, ISBN 978-3-540-19568-9 , PDF
  • Steven L. Tanimoto : Les éléments de l’intelligence artificielle utilisant Common Lisp , Computer Science Press, 1990, ISBN 0-7167-8230-8
  • Peter Lee : Sujets d’implémentation avancée du langage , The MIT Press, 1991, ISBN 0-262-12151-4
  • John H. Riley : A Common Lisp Workbook , Prentice Hall, 1991, ISBN 0-13-155797-1
  • Peter Norvig : Paradigmes de la programmation de l’intelligence artificielle : études de cas en Common Lisp , Morgan Kaufmann, 1991, ISBN 1-55860-191-0 , Web
  • Gregor Kiczales , Jim des Rivieres , Daniel G. Bobrow : L’art du protocole métaobjet , The MIT Press, 1991, ISBN 0-262-61074-4
  • Jo A. Lawless , Molly M. Miller : Comprendre CLOS : le système d’objets Common Lisp , Digital Press, 1991, ISBN 0-13-717232-X
  • Mark Watson: Common Lisp Modules: Artificial Intelligence in the Era of Neural Networks and Chaos Theory , Springer Verlag New York Inc., 1991, ISBN 0-387-97614-0 , PDF
  • James L. Noyes : Intelligence artificielle avec Common Lisp: Principes fondamentaux du traitement symbolique et numérique , Jones & Bartlett Pub, 1992, ISBN 0-669-19473-5
  • Stuart C. Shapiro : COMMON LISP : une approche interactive , Computer Science Press, 1992, ISBN 0-7167-8218-9 , Web/PDF
  • Kenneth D. Forbus , Johan de Kleer : Building Problem Solvers , The MIT Press, 1993, ISBN 0-262-06157-0
  • Andreas Paepcke : Programmation orientée objet: La perspective CLOS , The MIT Press, 1993, ISBN 0-262-16136-2
  • Paul Graham : On Lisp , Prentice Hall, 1993, ISBN 0-13-030552-9 , Web/PDF
  • Paul Graham : ANSI Common Lisp , Prentice Hall, 1995, ISBN 0-13-370875-6
  • Otto Mayer : Programmieren in Common Lisp , allemand, Spektrum Akademischer Verlag, 1995, ISBN 3-86025-710-2
  • Stephen Slade : Lisp commun orienté objet , Prentice Hall, 1997, ISBN 0-13-605940-6
  • Richard P. Gabriel : Patterns of Software: Tales from the Software Community , Oxford University Press, 1998, ISBN 0-19-512123-6 , PDF
  • Taiichi Yuasa , Hiroshi G. Okuno : Technologie Lisp avancée , CRC, 2002, ISBN 0-415-29819-9
  • David B. Lamkins : Lisp réussi: comment comprendre et utiliser Common Lisp , bookfix.com, 2004. ISBN 3-937526-00-5 , Web
  • Peter Seibel : Lisp commun pratique , Apress, 2005. ISBN 1-59059-239-5 , Web
  • Doug Hoyte : Let Over Lambda , Lulu.com, 2008, ISBN 1-4357-1275-7 , Internet
  • George F. Luger , William A. Stubblefield : Algorithmes IA, structures de données et idiomes en Prolog, Lisp et Java , Addison Wesley, 2008, ISBN 0-13-607047-7 , PDF
  • Conrad Barski : Land of Lisp : Apprenez à programmer en Lisp, un jeu à la fois ! , Presse sans amidon, 2010, ISBN 1-59327-200-6 , Web
  • Pavel Penev : Lisp Web Tales , Leanpub, 2013, Web
  • Edmund Weitz : Common Lisp Recipes , Apress, 2015, ISBN 978-1-484211-77-9 , Web
  • Patrick M. Krusenotto : Funktionale Programmierung und Metaprogrammierung, Interaktiv in Common Lisp , Springer Fachmedien Wiesbaden 2016, ISBN 978-3-658-13743-4 , Web

Liens externes

Wikibooks a plus sur le thème de: Common Lisp
  • Quicklisp – Un gestionnaire de bibliothèque très populaire et de haute qualité pour Common Lisp
  • La liste Awesome CL , une liste organisée de frameworks et de bibliothèques Common Lisp.
  • Le Common Lisp Cookbook , un projet collaboratif.
  • Le CLiki , un Wiki pour les systèmes Common Lisp gratuits et open-source fonctionnant sur des systèmes de type Unix.
  • Common-Lisp.net est l’un des principaux référentiels gratuits de Common Lisp pour les logiciels .
  • lisp-lang.org a de la documentation et une vitrine des histoires de réussite.
  • Un aperçu de l’histoire de Common Lisp : “Histoire” . Common Lisp HyperSpec .
  • Common Lisp Quick Reference – un aperçu compact du langage standard Common Lisp.
  • Planet Lisp Articles sur Common Lisp.
  • Quickdocs résume la documentation et les informations de dépendance pour de nombreux projets Quicklisp.
ANSI Common LispCommon LispCommon Lisp CommonCommon Lisp LispLisp Common Lisp
Comments (0)
Add Comment