Una macro per fare quello che vuoi
Come esercizio di una specie:
(defmacro setq-every (value &rest vars)
"Set every variable from VARS to value VALUE."
`(progn ,@(mapcar (lambda (x) (list 'setq x value)) vars)))
Ora provalo:
(setq-every "/foo/bar" f-loc1 f-loc2)
Come funziona
Dato che le persone sono curiose di sapere come funziona (secondo i commenti), ecco una spiegazione. Per imparare davvero a scrivere macro scegli un buon libro Common Lisp (sì, Common Lisp, sarai in grado di fare le stesse cose in Emacs Lisp, ma Common Lisp è un po 'più potente e ha libri migliori, IMHO).
Le macro operano su codice non elaborato. Le macro non valutano i loro argomenti (a differenza delle funzioni). Quindi abbiamo qui non valutato valuee la raccolta di vars, che per la nostra macro sono solo simboli.
prognraggruppa diverse setqforme in una. Questa cosa:
(mapcar (lambda (x) (list 'setq x value)) vars)
Genera solo un elenco di setqmoduli, usando l'esempio di OP sarà:
((setq f-loc1 "/foo/bar") (setq f-loc2 "/foo/bar"))
Vedete, il modulo è all'interno del modulo backquote ed è preceduto da una virgola
,. All'interno del modulo retroquistato, tutto viene quotato come al solito, ma la ,
valutazione "attiva" temporaneamente, quindi l'intero mapcarviene valutato al momento dell'espansione macro.
@Rimuove infine la parentesi esterna dall'elenco con setqs, quindi otteniamo:
(progn
(setq f-loc1 "/foo/bar")
(setq f-loc2 "/foo/bar"))
Le macro possono trasformare arbitrariamente il tuo codice sorgente, non è fantastico?
Un avvertimento
Ecco un piccolo avvertimento, il primo argomento verrà valutato più volte, poiché questa macro si espande essenzialmente a quanto segue:
(progn
(setq f-loc1 "/foo/bar")
(setq f-loc2 "/foo/bar"))
Vedi, se hai una variabile o una stringa qui va bene, ma se scrivi qualcosa del genere:
(setq-every (my-function-with-side-effects) f-loc1 f-loc2)
Quindi la tua funzione verrà chiamata più di una volta. Questo potrebbe essere indesiderabile. Ecco come risolverlo con l'aiuto di once-only(disponibile nel
pacchetto MMT ):
(defmacro setq-every (value &rest vars)
"Set every variable from VARS to value VALUE.
VALUE is only evaluated once."
(mmt-once-only (value)
`(progn ,@(mapcar (lambda (x) (list 'setq x value)) vars))))
E il problema è sparito.