我有一个宏,它将实现一个作为监听器的Java接口。我定义了宏来获取包含我想要解构的函数的映射,并用于每个接口方法。这是宏: -
(defmacro with-cache-listener-m [component event body]
(let [{:keys [f-insert f-update]} body]
`(. ~component addMapListener
(proxy [AbstractMapListener] []
(entryInserted [~event] ~f-insert ~event)
(entryUpdated [~event] ~f-update ~event)))))
身体地图是这样的: -
(def m-callbacks {:f-insert callback-insert :f-update callback-update})
但是当我致电(macroexpand '(with-cache-listener-m test-cache e m-callbacks))
时,它会扩展为(. test-cache user/addMapListener (clojure.core/proxy [com.tangosol.util.AbstractMapListener] [] (user/entryInserted [e] nil e) (user/entryUpdated [e] nil e)))
回调函数为零。我是否需要以不同的方式定义它们,或者我是否采取了错误的方式。
答案 0 :(得分:4)
当您调用with-cache-listener-m
宏时,body
参数作为符号绑定到'm-callbacks
,因此当您尝试对该局部变量进行解构时,它将无效,因为它是ain不是地图。您可以让生成的表单完成这样的工作:
(defmacro with-cache-listener-m [component event body]
`(let [{:keys [f-insert# f-update#]} ~body]
(. ~component addMapListener
(proxy [AbstractMapListener] []
(entryInserted [~event] f-insert# ~event)
(entryUpdated [~event] f-update# ~event)))))
但最后我不确定你的代码是否需要宏,你是否尝试将其编写为函数:
(defn add-map-listener [component insert-fn update-fn]
(.addMapListener component
(proxy [AbstractMapListener] []
(entryInserted [e] (insert-fn e))
(entryUpdated [e] (update-fn e)))))
如你所见,我改变了一些事情:
body
)的with- *宏不同。如果您想让这些功能完全可选,并且可以按任何顺序给出,您可以随时使用:
(defn add-map-listener [component & functions]
(let [{:keys [insert-fn update-fn]} (into {} functions)]
(when-not (empty? functions)
(.addMapListener component
(proxy [AbstractMapListener] []
(entryInserted [e] (insert-fn e))
(entryUpdated [e] (update-fn e)))))))
请注意,我没有在没有给出函数的情况下添加代码来调用addMapListener。
答案 1 :(得分:1)
宏不是函数:它们只知道在编译时传递给它们的文字形式。如果您为变量x
指定一个值(例如10),然后将x
传递给您的宏,则会看到不是10 x
。如果代替def
m-callbacks
然后传递该符号,那么您的宏可能会正常工作,您只需将地图直接作为文字传递。