如何从Java调用Clojure变量函数

如何从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 ;

是否可以在Clojure中声明一个变量函数,该函数可以作为Java中的varargs方法调用

考虑以下从一些正在开发的代码中摘录的内容:

(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数组->序列->扁平化参数列表->序列。