8

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

有任何想法吗?

编辑:即使以可以使用 ASM 库(而不是常规反射)访问的方式进行标记也可以,但我需要以某种方式标记实际AFunction对象或invoke方法。此外,我无法访问实际AFunction对象——我需要标签在类上可见。

4

2 回答 2

3

您可以使用 clojure 元数据功能,该功能允许将元数据(地图)附加到任何实现IMeta接口的对象(结果是每个对象,因为 IObj 扩展了 IMeta,每个对象都扩展了 IObj)

现在有2个选项。

1)您可以将元数据附加到var(var指向实际的IFn对象)

(defn hello {:name "hello"} [] 10)

在 Java 端,您获取 var hello 并使用 IMeta 方法获取元数据并检测您的特定元数据是否存在。这个问题可能是您的 Java 代码直接访问/处理 IFn 对象而不是它们的变量(例如:匿名函数),要解决这个问题,请尝试第二个选项。

2)将元数据附加到函数对象本身:

(def hello (with-meta (fn [] 10) {:name "hello"}))

您不能defn将元数据附加到 var。上面的示例代码将元数据附加到函数对象本身。在 Java 端,将函数对象类型化为 IMeta 并进行检查。上面的代码可以在defn作为练习的宏的帮助下变得更可爱:)

于 2013-04-10T12:19:34.693 回答
0

事实证明,如果用包含局部定义的 let 语句将函数体括起来,则该变量名称将出现在类文件中方法的局部表中。不过有点麻烦。还在寻找更好的方法。

于 2013-04-10T15:02:24.723 回答