For practice, I've defined
(defmacro quote-paren
"body -> `(body)"
[& body]
`(~@body))
which has the expected transformation (quote-paren body)
=> ``(body)`. It seems to satisfy a few basic tests:
user=> (macroexpand-1 `(quote-paren 3 4 5))
(3 4 5)
user=> (macroexpand-1 `(quote-paren println "hi"))
(clojure.core/println "hi")
user=> (macroexpand-1 `(quote-paren (println "hi")))
((clojure.core/println "hi"))
However, I've been testing it with this do-while macro (modified from here):
(defmacro do-while
[test & body]
(quote-paren loop []
~@body
(when ~test
(recur))))
(def y 4)
(do-while (> y 0)
(def y (dec y)))
But the result is
IllegalStateException Attempting to call unbound fn: #'clojure.core/unquote-splicing clojure.lang.Var$Unbound.throwArity (Var.java:43)
I don't understand this, because from what I can see the `quote-paren' macro works fine (with ~@body plugged in):
user=> (macroexpand-1
`(quote-paren loop []
(def y (dec y))
(when ~test
(recur))))
(clojure.core/loop [] (def user/y (clojure.core/dec user/y)) (clojure.core/when #<core$test clojure.core$test@1f07f672> (recur)))
But trying to macroexpand do-while
causes an "unbound fn
". Is there something subtle I'm missing?
missing the syntax-quote before quote-paren
user> (defmacro do-while
[test & body]
`(quote-paren loop []
~@body
(when ~test
(recur))))
#'user/do-while
which then expands properly:
user> (macroexpand '(do-while (> y 0)
(def y (dec y))))
(loop* [] (def y (dec y)) (clojure.core/when (> y 0) (recur)))
and seems to work:
user> (def y 4)
#'user/y
user> (do-while (> y 0)
(def y (dec y)))
nil
user>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With