Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 将函数映射传递给宏_Clojure - Fatal编程技术网

Clojure 将函数映射传递给宏

Clojure 将函数映射传递给宏,clojure,Clojure,我有一个宏,它将实现一个作为侦听器的Java接口。我将宏定义为获取包含要分解的函数的映射,并用于每个接口方法。这是宏:- (defmacro with-cache-listener-m [component event body] (let [{:keys [f-insert f-update]} body] `(. ~component addMapListener (proxy [AbstractMapListener] [] (entryInsert

我有一个宏,它将实现一个作为侦听器的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/addmapstener(clojure.core/proxy[com.tangosol.util.abstractmapstener][(user/entryInserted[e]nil e)(user/entryUpdated[e]nil e))


回调函数为nil。我是否需要以不同的方式定义它们,或者我的定义是错误的。

宏不是函数:它们只知道在编译时传递给它们的文本形式。如果给变量
x
指定一个值,比如10,然后将
x
传递给宏,它将看到的不是10,而是
x
。如果不使用
def
ing
m-callbacks
然后传递该符号,而直接将映射作为文本传递,则宏可能工作正常。

当调用
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)))))
但最后我不确定您的代码是否需要宏,您是否尝试将其作为函数编写:

(defn add-map-listener [component insert-fn update-fn]
  (.addMapListener component
    (proxy [AbstractMapListener] []
      (entryInserted [e] (insert-fn e))
      (entryUpdated [e] (update-fn e)))))
如你所见,我改变了两件事:

  • 使函数名更清晰,您的宏与其他带-*宏的宏不同,这些宏通常在某种特殊上下文中计算某些代码(代码体)
  • 删除了事件参数,因为它似乎没有任何用处
  • 使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)))))))

请注意,我添加了一些代码,以便在未提供任何函数时不调用addMapListener。

什么是回调插入和回调更新?当你调用m回调函数时,它会产生什么?它们只是两个函数,打印参数并返回。m-callbacks是user>m-callbacks{:f-insert#,:f-update#}如果将m-callbacks绑定到一个计算结果为该映射而不是直接计算到映射的函数,会怎么样?(defn m-callbacks2[]({:f-insert callback insert:f-update callback update}))相同的结果,在宏扩展中,这两个函数都是零。我想我真正想知道的是,任何定义了多个方法的Java侦听器接口如何在宏中以惯用方式实现。我尝试了以下方法:-user>(macroexpand)(with-cache-listener-m test cache e'{:f-insert callback insert:f-update callback update})(.test cache user/addmapstener(clojure.core/proxy[com.tangosol.util.abstractmapstener][](user/entryInserted[e]nil e)(user/entryUpdated[e]nil e)))这当然更清楚了,谢谢。但是,我仍然会得到相同的错误,就像我最初将其定义为函数时一样。我的函数映射是(defm-callbacks{:insert fn callback insert:update fn callback update}),但是当我调用add-map listener时,我得到一个异常,没有为key提供值。m-callbacks evals to user>m-callbacks{:insert fn#,:update fn#}首先,您需要像这样使用
apply
(apply add map listener m-callbacks)第二,我犯了一个小错误,
函数
参数需要转换回映射,现在已经修复了。您还可以使用args向量定义
添加映射侦听器
[组件函数]
,以便它直接将映射作为参数。按照我定义它的方式,您可以这样调用它:
(添加映射侦听器测试缓存:f-insert callback insert:f-update callback update)
(应用添加映射侦听器测试缓存m-callbacks)可以正常工作。谢谢你,这很有教育意义。我不确定我是否理解apply在这里的用法,但现在我将查找它。