Welcome! Please see the About page for a little more info on how this works.

+2 votes
in Clojure by

If you use with-redefs to redefine a macro (which is likely a mistake), the macro loses its macro status after the with-redefs call completes.

Presumably the fix depends on whether we think there is a valid use of with-redefs on a macro (which would only work if you're calling eval or equivalent in the body, and would require knowing enough about what you're doing to add the two extra macro args to your function) -- if so, we would keep it from losing the macro status; if not, we might also have it throw an exception if you accidentally use it on a macro.

Demonstration of the effect:

`
user> (defmacro kwote [arg] `(quote ~arg))

'user/kwote

user> (kwote hello)
hello
user> kwote
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'user/kwote, compiling:(/tmp/form-init6222001939841513290.clj:1:18983)

;; Everything above is as expected

user> (with-redefs [kwote (constantly :in-with-redefs)] (kwote with-redefs-body))
with-redefs-body
user> (kwote hello)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: hello in this context, compiling:(/tmp/form-init6222001939841513290.clj:1:1)
user> (kwote :arg-1)
ArityException Wrong number of args (1) passed to: user/kwote clojure.lang.AFn.throwArity (AFn.java:429)
user> (kwote :arg-1 :arg-2 :arg-3)
(quote :arg-3)
user> kwote

object[user$kwote 0x37e32ff6 "user$kwote@37e32ff6"]

`

2 Answers

0 votes
by

Comment made by: gfredericks

Looks like the root cause is that {{with-redefs}} uses 1. } which intentionally clears the macro flag: https://github.com/clojure/clojure/blob/5cfe5111ccb5afec4f9c73b46bba29ecab6a5899/src/jvm/clojure/lang/Var.java#L270

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-1867 (reported by gfredericks)
...