Qual è la differenza tra "set", "setq" e "setf" in Common Lisp?Differenza tra `set`,` setq` e `setf` in Common Lisp?
risposta
In origine, in Lisp, non c'erano variabili lessicali, solo dinamiche. E non c'era SETQ o SETF, solo la funzione SET.
Quello che oggi è scritto come:
(setf (symbol-value '*foo*) 42)
è stato scritto come:
(set (quote *foo*) 42)
che finalmente è stato abbreviavated a setq (SET Citato):
(setq *foo* 42)
variabili Poi lessicali successo e SETQ è stato utilizzato anche per l'assegnazione a questi - quindi non era più un semplice wrapper attorno a SET.
Più tardi, qualcuno ha inventato SETF (SET Field) come un modo generico di assegnazione di valori alle strutture di dati, per rispecchiare le t-valori delle altre lingue:
x.car := 42;
sarebbe scritto come
(setf (car x) 42)
Per simmetria e generalità, SETF ha fornito anche la funzionalità di SETQ. A questo punto sarebbe stato corretto dire che SETQ era una primitiva di basso livello, e SETF un'operazione di alto livello.
Quindi si sono verificati i simboli macro. In modo che le macro simbolo potrebbe funzionare in modo trasparente, si è capito che setq avrebbe dovuto agire come SETF se la "variabile" viene assegnato a era davvero una macro simbolo:
(defvar *hidden* (cons 42 42))
(define-symbol-macro foo (car *hidden*))
foo => 42
(setq foo 13)
foo => 13
*hidden* => (13 . 42)
Si arriva così al giorno d'oggi: SET e I SETQ sono resti atrofizzati di dialetti più vecchi e probabilmente verranno avviati da eventuali successori di Common Lisp.
Common Lisp ha sempre avuto variabili lessicali. Devi parlare di alcune Lisp prima di Common Lisp. –
Se SET e SETQ devono essere avviati da un successore Common Lisp, dovranno ottenere una sostituzione. Il loro uso nel codice di alto livello è limitato, ma il codice di basso livello (ad esempio, il codice SETF è implementato in) ne ha bisogno. – Svante
c'è un motivo per cui hai scelto 'auto' come un campo invece di qualcosa che potrebbe essere confuso come funzione dell'automobile? – drudru
setq
è come set
con un primo argomento quotato - (set 'foo '(bar baz))
è proprio come (setq foo '(bar baz))
. setf
, d'altra parte, è davvero sottile - è come una "indiretta". Suggerisco http://www.n-a-n-o.com/lisp/cmucl-tutorials/LISP-tutorial-16.html come un modo migliore per iniziare a comprenderlo rispetto a qualsiasi risposta qui può dare ... in breve, però, setf
prende il primo argomento come un "riferimento", così ad es. (aref myarray 3)
funzionerà (come il primo argomento a setf
) per impostare un elemento all'interno di un array.
Ha più senso per il nome setq. Facile da ricordare. Grazie. – CDR
(set ls '(1 2 3 4)) => Error - ls has no value
(set 'ls '(1 2 3 4)) => OK
(setq ls '(1 2 3 4)) => OK - make ls to (quote ls) and then have the usual set
(setf ls '(1 2 3 4)) => OK - same as setq so far BUT
(setf (car ls) 10) => Makes ls '(10 2 3 4) - not duplicated by setq/set
Trovo che la tua risposta sia più chiara di quella votata in alto. Molte grazie. – CDR
@Sourav, non utilizzare MAI la lettera "l" (ell) come variabile o simbolo nel codice di esempio. È troppo difficile distinguere visivamente dal numero 1. – DavidBooth
No, non riesco ancora a capire come (auto ls) possa essere un valore l o no. Capisci come tradurre CLisp in C? e come scrivere un interprete CLisp? – reuns
vorrei aggiungere alle risposte precedenti, che setf è macro che chiama la funzione specifica a seconda di ciò che è stato passato come primo argomento. Confrontare i risultati della macro espansione setf con diversi tipi di argomenti:
(macroexpand '(setf a 1))
(macroexpand '(setf (car (list 3 2 1)) 1))
(macroexpand '(setf (aref #(3 2 1) 0) 1))
Per alcuni tipi di argomenti "funzione setf" si chiamerà:
(defstruct strct field)
(macroexpand '(setf (strct-field (make-strct)) 1))
È possibile utilizzare setf
al posto di set
o setq
ma non viceversa poiché setf
può anche impostare il valore di singoli elementi di una variabile se la variabile ha singoli elementi. Vedere gli esempi di seguito:
Tutti e quattro gli esempi assegneranno la lista (1, 2, 3) alla variabile denominata 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
ha più la capacità di fissare un membro della lista in foo
ad un nuovo valore.
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)
Tuttavia, è possibile definire una macro simbolo che reprents un singolo elemento all'interno 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)
È possibile utilizzare defvar
se non l'hai già definito la variabile e non si vuole dare un valore fino a tardi nel tuo codice.
(defvar foo2)
(define-symbol-macro foo-car (car foo2))
Si può pensare SET
e SETQ
essere costrutti a basso livello.
SET
possibile impostare il valore di simboli.SETQ
può impostare il valore delle variabili.
Poi SETF
è una macro, che fornisce molti tipi di regolazione cose: simboli, variabili, elementi dell'array, slot istanza, ...
Per i simboli e variabili si può pensare come se SETF
espande in SET
e SETQ
.
* (macroexpand '(setf (symbol-value 'a) 10))
(SET 'A 10)
* (macroexpand '(setf a 10))
(SETQ A 10)
Così SET
e SETQ
vengono utilizzate per implementare alcune delle funzionalità di SETF
, che è il costrutto più generale. Alcune delle altre risposte ti dicono la storia un po 'più complessa, quando prendiamo in considerazione le macro dei simboli.
- 1. Qual è la differenza tra defvar, defparameter, setf e setq
- 2. common-lisp: differenza tra rilegatura e simbolo
- 3. Mandelbrot Imposta implementazione in Common Lisp
- 4. Differenza di struttura tra common lisp ed emacs lisp
- 5. Utilizzo di oggetto stringa come chiave hash in Common Lisp
- 6. Moltiplicazione matrice in Common Lisp
- 7. Association nel Common Lisp
- 8. Common Lisp definizione pacchetto
- 9. Come funziona append in Common Lisp?
- 10. (comporre) in Common Lisp
- 11. Stream in Common Lisp?
- 12. srotolare/argomenti splat in Common Lisp
- 13. Ridenominazione lambda in Common Lisp
- 14. Common lisp gray stream
- 15. Qual è la differenza tra eq, eql, equal e equalp, in Common Lisp?
- 16. Qual è la differenza tra require e load in common lisp?
- 17. Trasposizione di elenchi in Common Lisp
- 18. Come stampare un elenco come matrice in Common Lisp
- 19. definizione di espansioni di espansione in Common Lisp
- 20. Sviluppo Web in Common Lisp
- 21. Configurazione SLIME per lo sviluppo Common Lisp e Clojure
- 22. Programmazione ricca di tipo in Common Lisp?
- 23. Differenza tra set-cookie2 e set-cookie
- 24. Elenco circolare in Common Lisp
- 25. Esercizi Common Lisp/problemi
- 26. Qual è la differenza tra Lisp-1 e Lisp-2?
- 27. Differenza tra tuple e set in mdx
- 28. Aggiunta di carattere a stringa in Common Lisp
- 29. Disegno di alberi in Common Lisp
- 30. Perché Common Lisp non è sensibile al maiuscolo/minuscolo?
Il comportamento di questi viene risposto abbastanza bene nelle risposte, ma la risposta accettata ha un'etimologia forse errata per la "f" in "setf". La risposta a [cosa significa la f in setf sta per?] (Http://stackoverflow.com/q/23808189/1281433) dice che è per "funzione", e fornisce riferimenti per il backup. –