如何从Java调用Clojure变量函数
是否可以在Clojure中声明一个变量函数,该函数可以作为Java中的varargs方法调用 考虑以下从一些正在开发的代码中摘录的内容:如何从Java调用Clojure变量函数,java,clojure,interop,variadic-functions,Java,Clojure,Interop,Variadic Functions,是否可以在Clojure中声明一个变量函数,该函数可以作为Java中的varargs方法调用 考虑以下从一些正在开发的代码中摘录的内容: (ns com.mydomain.expression.base (:gen-class :name com.mydomain.expression.Base :methods [^:static [exprFactory [String String ?????] Object]] ) (defn expr-factory ;
(ns com.mydomain.expression.base
(:gen-class
:name com.mydomain.expression.Base
:methods [^:static [exprFactory [String String ?????] Object]]
)
(defn expr-factory
; worker function that is also called from Clojure
[id func & args]
(let [ex ("construction code here")]
ex))
(defn -exprFactory
; interface method called from Java
[idStr funcStr & argsArray]
(apply expr-factory idStr funcStr (seq argsArray)))
是否有什么可以替代??
,以允许Java调用exprFactory
方法并知道它是一个varargs方法:
import com.mydomain.expression.Base;
...
Object e1 = Base.exprFactory("e1", "day");
Object e2 = Base.exprFactory("e2", "length", "string");
Object e3 = Base.exprFactory("e3", "*", 4, 5);
Object sum = Base.exprFactory("sum", "+", e1, e2, e3);
为了更清楚一点,我知道我使用对象
来代替??
,并将exprFactory
更改为:
(defn -exprFactory
; interface method called from Java
[idStr funcStr argsArray]
(apply expr-factory idStr funcStr (seq argsArray)))
…但这意味着我必须编写如下Java调用:
import com.mydomain.expression.Base;
...
Object e1 = Base.exprFactory("e1", "day", new Object[0] ));
Object e2 = Base.exprFactory("e2", "length", new Object[] { "string" }));
Object e3 = Base.exprFactory("e3", "*", new Integer[] { 4, 5 }));
Object sum = Base.exprFactory("sum", "+", new Object[] { e1, e2, e3 }));
同样,我知道我可以用Java编写一个varargs包装器方法来调用非变量的
exprFactory
,但如果可能的话,我希望避免这种情况。我建议在Java端编写帮助器函数,类似于中的“applyToHelper”
这将采用Java函数的形式,该函数类似于:
public Object invokeVariadic(IFn function, Object... args) {
switch (args.length) {
case 0:
return function.invoke();
case 1:
return function.invoke(args[0]);
/// 20-odd more cases
}
}
这是一个小技巧,取决于的内部定义,但至少在Java端会得到相对不错的可变语法(即不需要做
新对象[]{…}
之类的事情)。@andrew这是我尝试的第一件事,我也尝试了对象。。。这将匹配Java语法。由于varargs只是编译器的一种欺骗,看起来就像类型签名中的数组,因此您应该能够使用以下命令指定字符串[]
:“[Ljava.lang.String;”
而不是?
。我试过了,它会编译,但eclipse不会识别varargs,它坚持使用字符串[]
即使java类和gen类都有相同的SIG类型。你可能会有更多的luckI知道这是可能的,因为Datomic做到了这一点……我认为这目前是不可能的。我将我的调查结果发布到clojure ML-@sw1nn上,感谢你进一步跟进。我已经尽可能使用你的伎俩迫使java方面提供数组,但不要使用首选的变量语法。最好能从Clojure中找到一种干净的方法来实现这一点-可能是:方法[^:static[exprFactory[String-String&Object]Object]]
并让Clojure自动将数组解释为一个序列。我认为这对于我试图实现的目标来说可能有些过分。为清楚起见,在Clojure方面,我希望最终使用可选的参数序列(表达式的操作数)调用expr factory
-对该序列的引用存储在返回的对象中。(应用…)-exprFactory
函数中的
表单仅用于扩展Java数组。也许有一种更有效的方法可以连接-exprFactory
和expr工厂
,因为我知道参数当前来自Java数组->序列->扁平化参数列表->序列。