Reputation: 23154
Here is the code:
(defmacro cond2 [& body]
(when body
`(if ~(first body)
~(if (next body)
(second body)
(throw (IllegalArgumentException. "error")))
~(cond2 (next (next (body)))))))
(cond2 (> 2 1) (println "2 > 1")
:else (println "2 <= 1"))
I got this error:
CompilerException java.lang.ClassCastException: clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn, compiling:(/Users/personal_config_bin_files/workspace/cina/src/cina/ref_types.clj:1:24)
If I remove the recursive part, the error goes away:
(defmacro cond2 [& body]
(when body
`(if ~(first body)
~(if (next body)
(second body)
(throw (IllegalArgumentException. "error")))
)))
this only works for a body with two clauses, of course.
If I quote the recursive part like this:
(defmacro cond2 [& body]
(when body
`(if ~(first body)
~(if (next body)
(second body)
(throw (IllegalArgumentException. "error")))
`(cond2 ~(next (next body))))))
then I get a different error:
CompilerException java.lang.RuntimeException: No such var: cina.ref-types/body, compiling:(/Users/personal_config_bin_files/workspace/cina/src/cina/ref_types.clj:331:5)
Using cons
instead of syntax-quote works:
(defmacro cond2 [& body]
(when body
`(if ~(first body)
~(if (next body)
(second body)
(throw (IllegalArgumentException. "error")))
~(cons 'cond2 (next (next body))))))
(cond2 (> 2 3) (println "good")
:else (println "bad"))
But I don't know what the difference is. Could anyone explain?
Upvotes: 1
Views: 1425
Reputation: 23154
It's unquote-splice that I need here:
(defmacro cond2 [& body]
(when body
`(if ~(first body)
~(if (next body)
(second body)
(throw (IllegalArgumentException. "error")))
(cond2 ~@(next (next body))))))
Upvotes: 1
Reputation: 2759
The problem is the (body)
in your original recursive part - it tries to call body
as a function, and then complains that it cannot cast the seq to a function.
Do (next (next body))
instead, and it should work fine.
Upvotes: 0