¿Cómo se expande una macro en clojure?
Frecuentes
Visto 668 equipos
3
En el libro Programación Clojure (Stuart), cuando leí cómo se expanden las macros me confundí.
user=> (defmacro chain
([x form] (list '. x form))
([x form & more] (concat (list 'chain (list '. x form)) more)))
#'user/chain
La macro anterior se puede expandir como:
user=> (macroexpand '(chain a b c))
(. (. a b) c)
Pero lo siguiente solo se expande al primer nivel:
user=> (macroexpand '(and a b c))
(let* [and__3822__auto__ a]
(if and__3822__auto__ (clojure.core/and b c) and__3822__auto__))
LA y fuente de macros:
user=> (source and)
(defmacro and([] true)
([x] x)
([x & next]
`(let [and# ~x]
(if and# (and ~@next) and#))))
Porque es el cadena la macro se expandió por completo, pero la y no ? ¿Por qué no se expande a algo como lo siguiente:
user=> (macroexpand '(chain a b c d))
(. (chain a b c) d)
2 Respuestas
2
macroexpand
expande la forma más externa una y otra vez hasta que obtiene un resultado no macro. Si desea ver solo la salida de una sola fase de macroexpansión, use macroexpand-1
.
Entonces la diferencia es, chain
La llamada recursiva de es primero, y and
no lo es.
Respondido 04 Jul 12, 04:07
2
Para mí, la respuesta de amalloy responde directamente a su pregunta. Sin embargo, si está velado debajo de su pregunta, se pregunta cómo mostrar la forma completamente macroexpandida de algo, le indicaría la dirección de clojure.caminar's macroexpand-all
. Usando su mismo ejemplo, ahora con macroexpand-all:
user=> (macroexpand-all '(and a b c))
(let* [and__3546__auto__ a]
(if and__3546__auto__
(let* [and__3546__auto__ b]
(if and__3546__auto__ c and__3546__auto__))
and__3546__auto__))
Todas las macros se han ampliado. También tenga en cuenta que para su primer ejemplo, se comportará igual que macroexpand
(por las razones que amalloy dio):
user=> (macroexpand-all '(chain a b c))
(. (. a b) c)
Respondido 05 Jul 12, 05:07
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas macros clojure expand or haz tu propia pregunta.