sortie inattendue avec les inconvénients ()
-
28-09-2019 - |
Question
Je suis d'un fond impératif, mais ces jours-ci en essayant mes mains sur LISP (Common Lisp)
Je lis ici sur cons
que
(contre x L):
Étant donné un objet de LISP x et une liste L, l'évaluation (cons x L) crée une liste contenant x suivies par les éléments en L.
Quand je intentionnellement ne pas utiliser une liste comme deuxième argument i.e. quand je
(cons 'a 'a)
je me attendais à une erreur, mais whoa! Je suis (A . A)
.
Qu'est-ce que j'ai manqué et ce qui est (A . A)
?
La solution
Cons
construit une "cellule de contre". Cela n'a rien à voir avec des listes dans un premier temps. Une cellule de contre est une paire de deux valeurs. Une cellule de contre est représenté sous forme écrite par une « paire pointillé », par exemple, (A . B)
, qui maintient les deux valeurs 'A
et 'B
.
Les deux endroits dans une cellule de contre sont appelés « voiture » et « cdr ». Vous pouvez visualiser une telle cellule de contre comme un bloc coupé en deux:
car cdr
+-----+-----+
| A | B |
+-----+-----+
En Lisp, une valeur peut aussi être une référence à quelque chose d'autre, par exemple, une autre cellule de contre:
+-----+-----+ +-----+-----+
| A | --------> | B | C |
+-----+-----+ +-----+-----+
Ce serait représenté sous forme de « paire pointillé » comme (A . (B . C))
. Vous pouvez continuer comme ça:
+-----+-----+ +-----+-----+ +-----+-----+
| A | --------> | B | --------> | C | D |
+-----+-----+ +-----+-----+ +-----+-----+
Ceci est (A . (B . (C . D)))
. Comme vous pouvez le voir, dans la structure telle, les valeurs sont toujours dans le car
d'une cellule de contre, et les points de cdr
au reste de la structure. Une exception est la dernière valeur, qui est dans la dernière cdr
. On n'a pas besoin de cette exception, cependant: il y a une valeur particulière NIL
dans Lisp, qui signifie « rien ». En mettant NIL
dans le dernier cdr
vous avez d'une valeur sentinelle à portée de main, et tous vos valeurs sont dans les car
s:
+-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+
| A | --------> | B | --------> | C | --------> | D | NIL |
+-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+
Voici comment une liste est construite en Lisp. Depuis (A . (B . (C . (D . NIL))))
est difficile à manier bits, il peut aussi être représenté simplement (A B C D)
. NIL
est aussi appelée la liste vide ()
; ce sont des notations pour la même permutables chose.
Maintenant, vous pouvez voir pourquoi (cons x list)
retourne une autre liste. Cons
construit simplement une autre cellule cons avec x
dans le car
et une référence à list
dans le cdr
:
+-----+-----+
| X | --------> list
+-----+-----+
et si list
est (A B)
, cela fonctionne comme:
+-----+-----+ +-----+-----+ +-----+-----+
| X | --------> | A | --------> | B | NIL |
+-----+-----+ +-----+-----+ +-----+-----+
Alors, évalue de (cons x '(a b))
à (x a b)
.
Les listes ne sont qu'une utilisation très fréquente des cellules Cons. Vous pouvez également construire des cellules arbres arbitraires de cons, ou des listes circulaires, ou tout graphe orienté, en fait.
Autres conseils
'a
est un atome de Lisp et (A . A)
est une liste dégénérée appelée contre cellulaire ou " paire en pointillés ». Puisque vous n'avez pas passé une liste pour L
argument en (cons x L)
vous êtes retourné une cellule.
(CONS x L)
Étant donné x et L, les retours CONS une nouvelle cellule cons avec x comme la voiture de cette cellule et de L en tant que CDR de cette cellule.
Les listes sont des chaînes liées de cellules Cons.
CL-USER 141 > (sdraw '(a b c))
[*|*]--->[*|*]--->[*|*]---> NIL
| | |
v v v
A B C
CL-USER 142 > (sdraw (cons 'foo '(a b c)))
[*|*]--->[*|*]--->[*|*]--->[*|*]---> NIL
| | | |
v v v v
FOO A B C
Si CONS obtient deux symboles comme argument, elle ressemble à ceci:
CL-USER 143 > (sdraw (cons 'foo 'bar))
[*|*]---> BAR
|
v
FOO