Quelle est la différence entre "set", "setq" et "setf" en Common Lisp?
common-lisp
Richard Hoskins
la source
la source
Réponses:
À l'origine, en Lisp, il n'y avait pas de variables lexicales - seulement des variables dynamiques. Et il n'y avait ni SETQ ni SETF, juste la fonction SET.
Ce qui s'écrit maintenant:
a été écrit comme:
qui a finalement été abrégé en SETQ (SET cité):
Ensuite, les variables lexicales sont apparues et SETQ a également été utilisé pour leur attribution - ce n'était donc plus un simple wrapper autour de SET.
Plus tard, quelqu'un a inventé SETF (SET Field) comme moyen générique d'attribuer des valeurs aux structures de données, pour refléter les valeurs l d'autres langages:
serait écrit comme
Pour la symétrie et la généralité, SETF a également fourni la fonctionnalité de SETQ. À ce stade, il aurait été correct de dire que SETQ était une primitive de bas niveau et SETF une opération de haut niveau.
Ensuite, des macros de symboles se sont produites. Pour que les macros de symboles puissent fonctionner de manière transparente, il a été réalisé que SETQ devrait agir comme SETF si la "variable" affectée était vraiment une macro de symboles:
Nous arrivons donc aujourd'hui: SET et SETQ sont des restes atrophiés d'anciens dialectes, et seront probablement démarrés à partir d'éventuels successeurs de Common Lisp.
la source
f
représente en fait une fonction , pas un champ (ou un formulaire , d'ailleurs), et fournit des références, donc bien que le setf pour champ ait un certain sens, il semble que ce ne soit pas correct.set
est une fonction. Ainsi, il ne connaît pas l'environnement.set
ne peut pas voir la variable lexicale. Il ne peut définir que la valeur de symbole de son argument.setq
n'est plus "set quoted". Le fait qu'ilsetq
s'agisse d'une forme spéciale et non d'une macro le montre.la source
(setq ls '(((1))))
,(setf (car (car (car ls))) 5)
est un comportement indéfini, car la valeur dels
est constante (comme la modification d'un littéral de chaîne en C). Après(setq ls (list (list (list 1))))
,(setf (car (car (car ls))) 5)
fonctionne commels->val->val->val = 5
dans C.setq
est juste commeset
avec un premier argument cité -(set 'foo '(bar baz))
est juste comme(setq foo '(bar baz))
.setf
, d'autre part, est en effet subtile - c'est comme une "indirection". Je suggère http://www.nano.com/lisp/cmucl-tutorials/LISP-tutorial-16.html comme un meilleur moyen de commencer à le comprendre que toute réponse ici peut donner ... en bref, cependant,setf
prend le premier argument comme "référence", de sorte que par exemple(aref myarray 3)
fonctionnera (comme le premier argument àsetf
) pour définir un élément dans un tableau.la source
Vous pouvez utiliser
setf
à la placeset
ousetq
mais pas l'inverse, car voussetf
pouvez également définir la valeur des éléments individuels d'une variable si la variable a des éléments individuels. Voir les exemples ci-dessous:Les quatre exemples attribueront la liste (1, 2, 3) à la variable nommée foo.
setf
a la capacité supplémentaire de définir un membre de la liste dansfoo
une nouvelle valeur.Cependant, vous pouvez définir une macro de symboles qui représente un seul élément dans
foo
Vous pouvez utiliser
defvar
si vous n'avez pas déjà défini la variable et ne souhaitez pas lui donner de valeur plus tard dans votre code.la source
On peut penser
SET
etSETQ
être des constructions de bas niveau.SET
peut définir la valeur des symboles.SETQ
peut définir la valeur des variables.Ensuite, il
SETF
y a une macro, qui fournit de nombreux types de paramètres: symboles, variables, éléments de tableau, emplacements d'instance, ...Pour les symboles et les variables, on peut penser comme si se
SETF
développait enSET
etSETQ
.Donc
SET
etSETQ
sont utilisés pour implémenter certaines des fonctionnalités deSETF
, qui est la construction la plus générale. Certaines des autres réponses vous racontent une histoire un peu plus complexe, lorsque nous prenons en compte les macros de symboles.la source
Je voudrais ajouter aux réponses précédentes que setf est une macro qui appelle une fonction spécifique en fonction de ce qui a été passé comme premier argument. Comparez les résultats de l'extension macro de setf avec différents types d'arguments:
Pour certains types d'arguments, la "fonction setf" sera appelée:
la source