我有以下的Clojure代碼:爲什麼我的宏的表單在函數調用之前未被評估?
(defn mul [a b]
(* a b))
(defmacro create-my-macro [macroname]
`(defmacro ~macroname [a# b#]
(mul a# b#)))
(create-my-macro my-mul)
(my-mul 1 2)
;; => 2
(my-mul (+ 1 1) 2)
;; => ClassCastException clojure.lang.PersistentList cannot be cast to java.lang.Number
我得到了我想要當我eval
包裹論點的mul
調用的答案:
(mul (eval #a) (eval #b))
但我不明白爲什麼它有必要這樣做:如果my-mul
宏已經被直接定義(而不是通過另一個宏),它就會起作用。例如,以下工作正常:
(defmacro my-mul [a b] `(mul ~a ~b))
(my-mul (+ 1 1) 2)
;; => 4
爲什麼我看到這種行爲?
編輯:迴應評論,下面是發生故障的情況下,macroexpands(即不使用eval
):
(macroexpand '(create-my-macro my-mul))
;; => (do
;; (clojure.core/defn my-mul
;; ([&form &env a__58__auto__ b__59__auto__]
;; (foo/mul a__58__auto__ b__59__auto__)))
;; (. (var my-mul) (setMacro)) (var my-mul))
(macroexpand '(my-mul (+ 1 1) 2))
;; => ClassCastException clojure.lang.PersistentList cannot be cast to java.lang.Number clojure.lang.Numbers.multiply (Numbers.java:146)
調試提示:這是什麼macroexpand說明了什麼? – 2013-02-28 08:16:00
剛剛添加他們 – 2013-02-28 08:39:44