Consider the following function
(defn shove [data fun] (eval `(-> ~data ~fun)))
which works as expected here
(shove [1 2 3] count) ;; ~~> 3
and even here, where it expectedly fails, because it evaluates (count) too early
(shove [1 2 3] (count))
;; ~~> clojure.lang.Compiler$CompilerException: clojure.lang.ArityException:
;; Wrong number of args (0) passed to: core$count, compiling:(null:5:1)
But here, when I define an explicit form and pass it to the function as data, all is well:
(def move '(count))
(shove [1 2 3] move) ;; ~~> 3
Now, in an attempt to get rid of the explicit call of eval, I try
(defmacro shovem [data form] `(-> ~data ~form))
which works fine
(shovem [1 2 3] count) ;; ~~> 3
(shovem [1 2 3] (count)) ;; ~~> 3
but it now unexpectedly fails on the explicitly defined form move, with an error that suggests that it evaluates move to get (count) and then keeps trying to evaluate (count), but in a different way than before.
(shovem [1 2 3] move)
;; ~~> java.lang.ClassCastException:
;; clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
I'm confused about this error message and I don't know how to get the desired behavior, which is that shovem should work on all three kinds of input, bare functions like count, parenthesized function forms like (count), and data objects like move that evaluate to such forms.
I'm ok with using eval in the function version, but, at this point, I realize I don't understand what's going on and I want to complete the exercise so as to improve my understanding.
macroexpandto see what your macro call is actually generating - johnbakers