2012-05-02 21 views
11

ClojureでJavaからvarargsメソッドと呼ばれる可変関数を宣言できますか? JavaからClojureバリデーション関数を呼び出す方法

は開発中のいくつかのコードからこの抜粋を考えてみましょう:

(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メソッドを呼び出すことができるように?????の場所に置くことができ、それは可変引数メソッドであることを知っているものがあります:

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); 

これは少し明確にするために、私は私が?????の代わりにObjectを使用して知っているにexprFactoryを変更します。

0123私は、Javaを記述しなければならないことを意味
(defn -exprFactory 
    ; interface method called from Java 
    [idStr funcStr argsArray] 
    (apply expr-factory idStr funcStr (seq argsArray))) 

..butは次のように呼び出します。

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 })); 

繰り返しますが、私は非可変引数exprFactoryを呼び出すJavaで可変引数のラッパー・メソッドを書くことができる知っているが、私は」可能ならばそれを避けるのが好きです。

+0

Object []が機能しません。 –

+0

@andrewこれは私が試した最初のもので、Object ...を試しましたが、これはJava構文と一致します。 –

+1

varargsは型シグネチャの配列のように見えるコンパイラのカンニングにすぎないので、これで '' String [] ''を指定できるはずです: '' [Ljava.lang.String; "' '' ????? ''の代わりに '' ???私はそれをコンパイルしようとしましたが、eclipseはvarargsを認識しません。javaクラスとgenクラスのクラスでも同じ型シグニチャを持っていても '' String [] ''を主張します。あなたはもっと運があるかもしれない – sw1nn

答えて

1

私は、Java側にこのようなものに見えるJava関数の形を取るclojure.lang.AFn

に「applyToHelper」のようなものを、あなたのヘルパー関数を書くことをお勧め:

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 
    } 
    } 

にですちょっとハックしてclojure.lang.IFnの内部定義に依存していますが、少なくともJava側では比較的良い可変構文が得られます(つまり、new Object[] {...}を実行する必要はありません)。

+0

私は達成しようとしていることが過度のことかもしれないと思います。わかりやすくするために、Clojure側では、オプションの引数シーケンス(式のオペランド)を指定して 'expr-factory'を最終的に呼び出したいと思います。返された' Object'にそのシーケンスへの参照が格納されます。 '-exprFactory'関数中の'(apply ...) '形式は、Java配列を展開するためだけに使用されます。おそらくargsが現在Java配列 - > sequence - > flattened arg list - > sequenceから出てくることを知っているので、 '-exprFactory'と' expr-factory'をインタフェースするより効率的な方法があります。 –

関連する問題