Can Clojure generate function by macro?

2019-07-13 19:16发布

问题:

I'm trying to generator fn through macro.But I meet a strange issue. Code is Here.

(defmacro test2 [lmk]
   (fn [lmk2] (println lmk lmk2)))
((test2 12) 13) ;;----->Error
(defmacro test3 []
   (fn [lmk] (println lmk)))
((test3) 12) ;;----->OK
(defmacro test4 []
   `(fn [lmk] (println lmk)))
((test4) 12) ;;----->Error

I know defn can work well.I just want to know why I can't use defmacro here.And why test3 works well,however test2 fails.

回答1:

In test2, prior to compilation, the test2 macro will be invoked (lmk has not yet been compiled or evaluated) - because there is no syntax quote, this will actually evaluate the fn form and return a function object (with lmk closed over). So you then have the form (fn-object 13) passed to the compiler, which I think is going down an unexpected path (not sure exactly what that is). Interestingly this works:

(def f (test2 12))
(f 13)

In test4, the syntax quote will cause each lmk symbol to be resolved in the namespace so that's the source of that error. You really want autogensyming on those:

(defmacro test4 [] 
  `(fn [lmk#] (println lmk#)))