Quelle est la différence entre « set », « setq » et « setf » en Common Lisp ?
Réponses
Trop de publicités?À l'origine, en Lisp, il n'y avait pas lexicales variables-dynamiques uniquement. Et il n'y a pas de SETQ ou SETF, juste la fonction de configuration.
Ce qui est maintenant écrit:
(setf (symbol-value '*foo*) 42)
a été écrit comme:
(set (quote *foo*) 42)
qui a finalement été abbreviavated à SETQ (SET Cité):
(setq *foo* 42)
Puis lexicale variables qui s'est passé, et SETQ est venu à être utilisé pour l'affectation à eux, de sorte qu'il n'était plus un simple wrapper autour de l'ENSEMBLE.
Plus tard, quelqu'un a inventé SETF (JEU de Champ) comme un moyen générique de l'affectation de valeurs à des structures de données, afin de refléter la l-valeurs des autres langues:
x.car := 42;
serait écrit comme
(setf (car x) 42)
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 a un Faible niveau primitif, et SETF une opération de haut niveau.
Ensuite, symbole de macros qui s'est passé. De sorte que le symbole de macros peut travailler en toute transparence, il a été réalisé que SETQ aurait à agir comme SETF si la "variable" d'être affecté à était vraiment un symbole de la macro:
(defvar *hidden* (cons 42 42))
(define-symbol-macro foo (car *hidden*))
foo => 42
(setq foo 13)
foo => 13
*hidden* => (13 . 42)
Nous arrivons donc dans le présent jour: et SETQ sont athropied reste des anciens dialectes, et va probablement être démarré à partir d'éventuels successeurs de Common Lisp.
setq
est juste comme set
avec une cité en premier arg -- (set 'foo '(bar baz))
est juste comme (setq foo '(bar baz))
. setf
, d'autre part, est subtile en effet-c'est comme un "indirection". Je suggère http://www.n-a-n-o.com/lisp/cmucl-tutorials/LISP-tutorial-16.html comme une meilleure façon d'obtenir commencé à comprendre que n'importe quelle réponse ici... bref, même si, setf
prend le premier argument comme une "référence", de sorte que, par exemple, (aref myarray 3)
travailler (comme le premier arg pour setf
) pour définir un élément dans un tableau.
Vous pouvez utiliser setf
à la place de set
ou setq
mais pas vice-versa depuis setf
pouvez également définir la valeur de chacun des éléments d'une variable si la variable a des éléments individuels. Voir la exaples ci-dessous:
Tous les quatre exemples d'assigner la liste (1, 2, 3) à la variable nommée foo.
(set (quote foo) (list 1 2 3)) ;foo => (1 2 3)
(1 2 3)
(set 'foo '(1 2 3)) ;foo => (1 2 3) same function, simpler expression
(1 2 3)
(setq foo '(1 2 3)) ;foo => (1 2 3) similar function, different syntax
(1 2 3)
(setf foo '(1 2 3)) ;foo => (1 2 3) more capable function
(1 2 3)
setf
a ajouté la capacité de l'établissement d'un membre de la liste dans foo
, à une nouvelle valeur.
foo ;foo => (1 2 3) as defined above
(1 2 3)
(car foo) ;the first item in foo is 1
1
(setf (car foo) 4) ;set or setq will fail since (car foo) is not a symbol
4
foo ;the fist item in foo was set to 4 by setf
(4 2 3)
Toutefois, vous pouvez définir un symbole de la macro que reprents un seul élément dans le cadre d' foo
(define-symbol-macro foo-car (car foo)) ; assumes FOO => (1 2 3)
FOO-CAR
foo-car ;foo-car is now a symbol for the 1st item in foo
1
(setq foo-car 4) ;set or setq can set the symbol foo-car
4
foo ;Lisp macros are so cool
(4 2 3)
Vous pouvez utiliser defvar
si vous ne l'avez pas déjà défini la variable et ne veulent pas de lui donner une valeur jusqu'à ce que plus loin dans votre code.
(defvar foo2)
(define-symbol-macro foo-car (car foo2))
On peut penser à l' SET
et SETQ
étant faible niveau des constructions.
SET
pouvez définir la valeur de symboles.SETQ
pouvez définir la valeur des variables.
Ensuite, SETF
est une macro, qui offre de nombreux types de réglage de choses: des symboles, des variables, des éléments de tableau, exemple des fentes, ...
Pour les symboles et les variables, on peut penser que si SETF
se développe en SET
et SETQ
.
* (macroexpand '(setf (symbol-value 'a) 10))
(SET 'A 10)
* (macroexpand '(setf a 10))
(SETQ A 10)
Donc, SET
et SETQ
sont utilisés pour mettre en œuvre certaines des fonctionnalités de l' SETF
, ce qui est le plus général de construction. Certains des autres réponses vous en dire un peu plus sur l'histoire complexe, lorsque nous prenons le symbole des macros en compte.