2012-05-02 6 views
11

से क्लोजर वैरिएडिक फ़ंक्शन को कॉल करने के लिए कैसे करें क्लोजर में एक वैरैडिक फ़ंक्शन घोषित करना संभव है जिसे जावा से एक 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))) 

क्या मैं ????? के स्थान पर डाल जावा 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); 

इस एक छोटे से स्पष्ट बनाने के लिए, मैं मैं ????? के स्थान पर Object का उपयोग जानते हैं और करने के लिए exprFactory बदलने के लिए:

(defn -exprFactory 
    ; interface method called from Java 
    [idStr funcStr argsArray] 
    (apply expr-factory idStr funcStr (seq argsArray))) 

..लेकिन मतलब यह है कि मैं जावा इस तरह कहता है लिखने के लिए है:

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

फिर से, मैं जानता हूँ कि मुझे लगता है कि गैर variadic exprFactory कॉल जावा में एक varargs आवरण विधि लिख सकता है, लेकिन मैं अगर संभव हो तो इससे बचने के लिए।

+0

और ऑब्जेक्ट [] काम नहीं करता है? –

+0

@andrew मैंने पहली कोशिश की थी, और मैंने ऑब्जेक्ट की भी कोशिश की ... जो जावा सिंटैक्स से मेल खाती है। –

+1

क्योंकि varargs केवल कंपाइलर द्वारा धोखा देती है जो कि प्रकार हस्ताक्षर में एक सरणी की तरह दिखती है, आपको इसके साथ '' स्ट्रिंग [] '' निर्दिष्ट करने में सक्षम होना चाहिए: '' "[Ljava.lang.String;" ' '' ????? '' के बजाय '। मैंने कोशिश की, यह संकलित करता है, लेकिन ग्रहण varargs को पहचाना नहीं जाएगा, यह एक '' स्ट्रिंग [] '' एक जावा वर्ग के रूप में भी जोर देता है और एक जीन-क्लास वर्ग में समान प्रकार के सिग होते हैं। आपके पास अधिक भाग्य – sw1nn

उत्तर

1

मैं अपने सहायक समारोह, "applyToHelper" की तरह कुछ clojure.lang.AFn

में जावा तरफ लेखन सुझाव है कि यह एक जावा समारोह के फार्म का है कि तरह दिखता ले जाएगा:

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 की आंतरिक परिभाषा पर निर्भर करता है, लेकिन कम से कम आपको जावा पक्ष पर अपेक्षाकृत अच्छा वैरिएडिक सिंटैक्स मिलेगा (यानी new Object[] {...} सामान करने की आवश्यकता नहीं है)।

+0

मुझे लगता है कि मैं जो हासिल करने की कोशिश कर रहा हूं उसके लिए अधिक हो सकता है। स्पष्टता के लिए, क्लोजर पक्ष पर मैं आखिरकार तर्कों के वैकल्पिक अनुक्रम (अभिव्यक्ति के लिए संचालन) के साथ 'एक्सप्र-फैक्ट्री' को कॉल करना चाहता हूं - उस अनुक्रम को एक रिफ्रेंस 'ऑब्जेक्ट' में संग्रहीत किया जाता है। '-exprFactory' फ़ंक्शन में' (लागू ...) 'फ़ॉर्म का उपयोग केवल जावा सरणी का विस्तार करने के लिए किया जाता है। शायद '-exprFactory' और' expr-factory 'को इंटरफ़ेस करने का एक और अधिक प्रभावी तरीका है क्योंकि मुझे पता है कि वर्तमान में जावा सरणी -> अनुक्रम -> flattened arg list -> अनुक्रम से तर्क है। –

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^