我需要以某种方式将某些Clojure函数标记为“特殊”,以便Java代码可以使用反射识别它们。我试图在函数中添加注释,但显然不支持。我试图reify
扩展IFn
的接口(以便Java代码可以识别函数对象),但这并不好,因为Clojure没有直接使用reified方法作为实现{的代码{1}},而是间接调用实际实现该方法的invoke
对象(我需要使用实际的函数代码标记实际的Afunction
方法)。
有什么想法吗?
编辑:甚至以可以使用ASM库访问的方式标记(而不是常规反射)也没关系,但我需要以某种方式标记实际的invoke
对象或AFunction
方法。另外,我无法访问实际的invoke
对象 - 我需要在课堂上看到标签。
答案 0 :(得分:3)
你可以使用clojure元数据功能,它允许将元数据(地图)附加到任何实现IMeta
接口的对象(当IObj扩展IMeta并且每个对象扩展IObj时,结果为每个对象) )
现在有2种选择。
1)您可以将元数据附加到var(var指向实际的IFn对象)
(defn hello {:name "hello"} [] 10)
在Java端,您可以获得var hello并使用IMeta方法获取元数据并检测您的特定元数据是否存在。 这个问题可能是你的Java代码直接访问/处理IFn对象而不是他们的vars(例如:匿名函数),解决这个问题尝试第二个选项。
2)将元数据附加到函数对象本身:
(def hello (with-meta (fn [] 10) {:name "hello"}))
您不能将defn
用作附加元数据到var。上面的示例代码将元数据附加到函数对象本身。在Java端,将函数对象指定给IMeta并进行检查。
上面的代码可以在一个宏的帮助下变得更加defn
,这可以作为一个练习:)
答案 1 :(得分:0)
事实证明,如果用函数体包含一个包含本地定义的let语句,那么该变量名将出现在类文件的方法的本地表中。但有点麻烦。仍在寻找更好的方式。