将函数映射传递给宏

JPT*_*JPT 6 clojure

我有一个宏将实现一个作为监听器的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)))))
Run Code Online (Sandbox Code Playgroud)

人体图是这样的: -

(def m-callbacks {:f-insert callback-insert :f-update callback-update})
Run Code Online (Sandbox Code Playgroud)

但是,当我打电话给(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)))

回调函数为零.我需要以不同的方式定义它们,还是以错误的方式解决这个问题.

Nic*_*roi 4

当您调用with-cache-listener-m宏时,body参数会被限制为'm-callbacks符号,因此当您尝试解构该局部变量时,它将不起作用,因为它不是映射。您可以让生成的表单完成如下工作:

(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)))))
Run Code Online (Sandbox Code Playgroud)

但最后我不确定你的代码是否需要宏,你是否尝试将其编写为函数:

(defn add-map-listener [component insert-fn update-fn]
  (.addMapListener component
    (proxy [AbstractMapListener] []
      (entryInserted [e] (insert-fn e))
      (entryUpdated [e] (update-fn e)))))
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我改变了一些事情:

  • 使函数名称更清晰,您的宏并不像其他通常body在某种特殊上下文中评估某些代码( )的 with-* 宏。
  • 删除了事件参数,因为它似乎没有任何用处。
  • 明确 insert-fn 和 update-fn 参数以简化示例。
  • 使用新的方法调用语法。
  • 修复了代理的方法以实际使用给定的功能。

如果您想让这些功能完全可选并可以按任何顺序给出,您始终可以这样做:

(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)))))))
Run Code Online (Sandbox Code Playgroud)

请注意,我添加了代码,以便在未给出函数时不调用 addMapListener。