如何标记Clojure函数以便我可以使用Java反射识别它

时间:2013-04-10 11:14:26

标签: clojure clojure-java-interop

我需要以某种方式将某些Clojure函数标记为“特殊”,以便Java代码可以使用反射识别它们。我试图在函数中添加注释,但显然不支持。我试图reify扩展IFn的接口(以便Java代码可以识别函数对象),但这并不好,因为Clojure没有直接使用reified方法作为实现{的代码{1}},而是间接调用实际实现该方法的invoke对象(我需要使用实际的函数代码标记实际的Afunction方法)。

有什么想法吗?

编辑:甚至以可以使用ASM库访问的方式标记(而不是常规反射)也没关系,但我需要以某种方式标记实际的invoke对象或AFunction方法。另外,我无法访问实际的invoke对象 - 我需要在课堂上看到标签。

2 个答案:

答案 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语句,那么该变量名将出现在类文件的方法的本地表中。但有点麻烦。仍在寻找更好的方式。