Macros 为什么我的宏是';在函数调用之前,是否未计算s窗体?
我有以下Clojure代码:Macros 为什么我的宏是';在函数调用之前,是否未计算s窗体?,macros,clojure,Macros,Clojure,我有以下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.Pers
(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))
(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)
但我不明白为什么有必要这样做:如果直接定义了mymul
宏(而不是通过另一个宏),它就可以工作了。例如,以下方法可以很好地工作:
(defmacro my-mul [a b] `(mul ~a ~b))
(my-mul (+ 1 1) 2)
;; => 4
为什么我会看到这种行为
编辑:以下是失败案例的宏扩展(即不使用
eval
):
如图所示,您希望发出的代码如下所示:
(defmacro my-mul [a b] `(mul ~a ~b))
因此,您需要对其进行语法引用,并在所有局部变量后面加上#:
因此,发出宏的宏应为:
(defmacro create-my-macro [macroname]
`(defmacro ~macroname [a# b#]
`(mul ~a# ~b#)))
如图所示,您希望发出的代码如下所示:
(defmacro my-mul [a b] `(mul ~a ~b))
因此,您需要对其进行语法引用,并在所有局部变量后面加上#:
因此,发出宏的宏应为:
(defmacro create-my-macro [macroname]
`(defmacro ~macroname [a# b#]
`(mul ~a# ~b#)))
调试提示:macroexpand显示了什么?调试提示:macroexpand显示了什么?是的,你的答案比我的更详细:)是的,你的答案比我的更详细:)