2011-12-29 10 views
15
user=> (Integer/rotateRight 0 0) 
0 

user=> (apply Integer/rotateRight [0 0]) 
CompilerException java.lang.RuntimeException: Unable to find static field: 
    rotateRight in class java.lang.Integer, compiling:(NO_SOURCE_PATH:172) 

वहाँ किसी भी तरह से Clojure में जावा कार्यों के लिए आवेदन करते हैं करने के लिए है? यदि नहीं, तो मैं एक मैक्रो या फ़ंक्शन कैसे लिख सकता हूं जो इसका समर्थन करेगा?जावा कार्यों के लिए क्लोजर में कोई लागू फ़ंक्शन है?

+0

दिलचस्प: भविष्य के साथ ऑटो-विधि रैपर पीढ़ी को शामिल करने की योजनाएं क्लोजर कंपाइलर पुनः लिखना http://dev.clojure.org/display/design/Better+method+inference – Ambrose

उत्तर

17

सरल बात मैं के एक समारोह में यह लपेटकर है सोच सकते हैं, लेकिन मैं पूरी तरह से यकीन है कि अगर यह सबसे अच्छा/सबसे मुहावरेदार तरीका है नहीं कर रहा हूँ:

user> (apply (fn [a b] (Integer/rotateRight a b)) [0 0]) 
0 

या, थोड़ा कम लेकिन बराबर:

user> (apply #(Integer/rotateRight %1 %2) [0 0]) 
0 

फिर, आप अपने जावा विधि कॉल के लिए एक उचित आवरण समारोह बना सकते हैं:

(defn rotate-right [a b] 
    (Integer/rotateRight a b)) 

तुम इतनी है कि यह प्रयोग करना होगा:

user> (apply rotate-right [0 0]) 
0 

संपादित:

;; direct method call (x 1 million) 
user> (time (dorun (repeatedly 1E6 #(Integer/rotateRight 2 3)))) 
"Elapsed time: 441.326 msecs" 
nil 

;; method call inside function (x 1 million) 
user> (time (dorun (repeatedly 1E6 #((fn [a b] (Integer/rotateRight a b)) 2 3)))) 
"Elapsed time: 451.749 msecs" 
nil 

;; method call in function using apply (x 1 million) 
user> (time (dorun (repeatedly 1E6 #(apply (fn [a b] (Integer/rotateRight a b)) [2 3])))) 
"Elapsed time: 609.556 msecs" 
nil 
+1

यह बहुत चालाक है, मुझे आश्चर्य है कि मैं एक लिख सकता हूं मैक्रो जिसने मेरे लिए लिखा था। –

+1

आप शायद कर सकते थे, लेकिन व्यक्तिगत रूप से मुझे लगता है कि इसका लाभ पतला है: परिणामस्वरूप फॉर्म शायद ही कम होगा, और उपरोक्त कोड यह स्पष्ट करता है कि क्या हो रहा है। वैकल्पिक रूप से, आप फ़ंक्शन को परिभाषित कर सकते हैं और जावा विधि के बजाय कॉल कर सकते हैं। मैं चित्रण करने के लिए अपना जवाब संपादित करूंगा। – Gert

+0

मैं असहमत हूं। क्या होगा यदि आप कर सकते हैं (जे-लागू 'इंटीजर/rotateRight [0 0])? क्या यह अधिक संक्षिप्त नहीं होगा? –

0

मैं: सिर्फ मनोरंजन के लिए, इस विधि को बुलाने की तीन अलग अलग तरीकों के बीच के समय की तुलना, दक्षता के बारे में iradik की टिप्पणी से प्रेरित gertalot के जवाब से प्रेरित होने के बाद ऐसा करने के लिए कुछ मैक्रोज़ लिखा था। समकक्ष सामान्य कोड को संकलित करने के लिए प्रकट होता है। बेंचमार्क समान था। आप क्या सोचते हैं उत्सुक है।

(defmacro java-new-apply 
    ([klass] `(new ~klass)) 
    ([klass args] `(new ~klass [email protected](map eval args)))) 

(defmacro java-static-apply 
    ([f] f) 
    ([f args] `(~f [email protected](map eval args)))) 

(defmacro java-method-apply 
    ([method obj] method obj) 
    ([method obj args] `(~method ~obj [email protected](map eval args)))) 

;; get date for Jan 1 1969 
(import java.util.Date) 
(java-new-apply Date [69 1 1]) 
(macroexpand '(java-new-apply Date [69 1 1])) 
(new Date 69 1 1) 

(java-static-apply Integer/rotateRight [2 3]) 
(macroexpand '(java-static-apply Integer/rotateRight [2 3])) 
(. Integer rotateRight 2 3) 

(java-method-apply .substring "hello world!" [6 11]) 
(macroexpand '(java-method-apply .substring "hello world!" [6 11])) 
(. "hello world!" substring 6 11) 
+3

यह केवल तभी काम करता है जब आप अपने मैक्रोज़ को अक्षर भेजते हैं। इसे आज़माएं: '(मेरा दिनांक डेटा [69 1 1]) (मैक्रोएक्सपैंड' (जावा-नई-लागू तिथि मेरी तिथि-डेटा)) 'यह देखने के लिए कि यह काम नहीं करता है। मैक्रोज़ का विस्तार किया जाता है समय संकलित करें, रन टाइम नहीं, जिसका अर्थ है कि आपके पास पास किए गए वास्तविक मूल्यों तक पहुंच नहीं है। –

+0

मैंने [एक ही चीज़ की कोशिश की] (http://stackoverflow.com/a/4514494/506721) और अंत में पता चला कि यह रैपर कार्यों के साथ बेवकूफ समाधान की तुलना में इसके लायक नहीं है। –

+0

गोरान के साथ सहमत हों - कोई फर्क नहीं पड़ता कि आप इसे कैसे फिसलते हैं, आप हमेशा फ़ंक्शन कॉल के अंदर लिपटे एक विधि कॉल के साथ समाप्त हो जाएंगे। – Gert

4

कुछ बिंदु जो प्रत्यक्ष उत्तर नहीं देते हैं, यहां प्रासंगिक हैं।

पहले, जावा फ़ंक्शन नहीं है। इसमें केवल उदाहरण विधियां या स्थैतिक विधियां हैं। यह एक पैडेंटिक भेद की तरह प्रतीत हो सकता है, लेकिन इससे कोई फर्क पड़ता है (जैसा कि कुछ अन्य उदाहरणों में दिखाया गया है जहां स्थैतिक और उदाहरण आवंटन के लिए विभिन्न रूपों की आवश्यकता है)।

दूसरे, प्रकार प्रणालियों के बीच प्रतिबाधा बेमेल खेलने में आता है। जावा के लिए जावाश ढंग से पूरी तरह से एफपी समर्थन प्राप्त करने के लिए, इसे स्थाई रूप से टाइप करने की आवश्यकता होगी। यह काफी सही मायने में संतोषजनक ढंग से करने के लिए कठिन हो सकता है के लिए पता चला है (दृष्टिकोण है कि इस्तेमाल किया जा रहा है और जावा 8 में आ जाएगा की जानकारी के लिए लैम्ब्डा-देव मेलिंग सूची पर चर्चा को देखें)।

इन दो बिंदुओं से, हम Clojure से देख सकते हैं कि सबसे अच्छा हम वास्तव में क्या कर सकते हैं #() या इसी तरह के माध्यम से जावा तरीकों बुला करने के लिए एक "सभी दांव बंद कर रहे हैं" दृष्टिकोण का समर्थन करने के लिए है। क्लोजर केवल तर्क की धैर्य के आधार पर कॉल करने के लिए फॉर्मों के बीच चयन करेगा, इसलिए सही ओवरलोडेड जावा विधि को सुनिश्चित करने के लिए कुछ प्रकार के संकेत संकेत या कास्टिंग की आवश्यकता हो सकती है।

इससे भी महत्वपूर्ण बात, बेशक, एक उपयोगकर्ता एक प्रकार है कि जावा की उम्मीद नहीं है, या संभाल सकते हैं की एक तर्क गुजरता है, तो यह नहीं क्रम जब तक पता लगाने योग्य हो सकता है।

+0

सही। मैं जानना चाहता हूं कि इंस्टेंस की विधि पर एक उदाहरण-विधि कैसे कॉल करें। – Timo

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