160 votes

Différence entre « set », « setq » et « setf » Lisp en commun ?

Quelle est la différence entre « set », « setq » et « setf » en Common Lisp ?

165voto

stack programmer Points 1678

À 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.

134voto

Sourav Points 481
(set l '(1 2 3 4)) => Error - l has no value

(set 'l '(1 2 3 4)) => OK

(setq l '(1 2 3 4)) => OK - make l to (quote l) and then have the usual set

(setf l '(1 2 3 4)) => OK - same as setq so far BUT

(setf (car l) 10) => Makes l '(10 2 3 4) - not duplicated by setq/set

21voto

Alex Martelli Points 330805

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.

16voto

dansalmo Points 3220

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))

13voto

Rainer Joswig Points 62532

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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X