जावा से क्लोजर बुला रहा है


165

"Java से कॉलिंग क्लूअर" के लिए शीर्ष Google हिट में से अधिकांश पुराने हैं और clojure.lang.RTस्रोत कोड को संकलित करने के लिए उपयोग करने की सलाह देते हैं । आप जावा से क्लोजर को कॉल करने के तरीके की स्पष्ट व्याख्या करने में मदद कर सकते हैं।


8
मुझे नहीं पता कि हर बार स्रोत को संकलित करना "पुराना" है। यह एक डिजाइन निर्णय है। मैं कर रहा हूँ कि अब के रूप में यह एक विरासत जावा Netbeans एक तस्वीर में Clojure कोड को एकीकृत करता है। एक पुस्तकालय के रूप में क्लोजर जोड़ें, एक क्लोजर स्रोत फ़ाइल जोड़ें, कॉल को सेटअप करें, और कई संकलन / लिंकिंग चरणों के बिना तत्काल क्लोजर समर्थन! प्रत्येक ऐप शुरू होने पर एक सेकंड की देरी के एक अंश की कीमत पर।
ब्रायन नोब्लुक


2
क्लोजर 1.8.0 के लिए नवीनतम देखें - क्लोजर में अब संकलक डायरेक्ट लिंकिंग है।
TWR कोल

जवाबों:


167

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

यह एक जार को संकलित करने और आंतरिक तरीकों को कॉल करने के रूप में काफी सरल नहीं है। हालांकि यह सब काम करने के लिए कुछ तरकीबें लगती हैं। यहाँ एक साधारण क्लोजर फ़ाइल का उदाहरण दिया गया है जिसे जार में संकलित किया जा सकता है:

(ns com.domain.tiny
  (:gen-class
    :name com.domain.tiny
    :methods [#^{:static true} [binomial [int int] double]]))

(defn binomial
  "Calculate the binomial coefficient."
  [n k]
  (let [a (inc n)]
    (loop [b 1
           c 1]
      (if (> b k)
        c
        (recur (inc b) (* (/ (- a b) b) c))))))

(defn -binomial
  "A Java-callable wrapper around the 'binomial' function."
  [n k]
  (binomial n k))

(defn -main []
  (println (str "(binomial 5 3): " (binomial 5 3)))
  (println (str "(binomial 10042 111): " (binomial 10042 111)))
)

यदि आप इसे चलाते हैं, तो आपको कुछ इस तरह देखना चाहिए:

(binomial 5 3): 10
(binomial 10042 111): 49068389575068144946633777...

और यहाँ एक जावा प्रोग्राम है जो -binomialफ़ंक्शन को कॉल करता है tiny.jar

import com.domain.tiny;

public class Main {

    public static void main(String[] args) {
        System.out.println("(binomial 5 3): " + tiny.binomial(5, 3));
        System.out.println("(binomial 10042, 111): " + tiny.binomial(10042, 111));
    }
}

यह आउटपुट है:

(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263

मैजिक का पहला टुकड़ा स्टेटमेंट :methodsमें कीवर्ड का उपयोग कर रहा है gen-class। ऐसा लगता है कि आपको जावा में स्थिर तरीकों की तरह क्लोजर फ़ंक्शन का उपयोग करने की आवश्यकता है।

दूसरी बात यह है कि एक रैपर फ़ंक्शन बनाया जाए जिसे जावा द्वारा बुलाया जा सके। ध्यान दें कि इसके सामने दूसरे संस्करण में -binomialडैश है।

और निश्चित रूप से क्लोजर जार खुद को क्लास पथ पर होना चाहिए। इस उदाहरण ने क्लोजर-1.1.0 जार का उपयोग किया।

अद्यतन : निम्नलिखित उपकरणों का उपयोग करके इस उत्तर को फिर से परखा गया है:

  • क्लोजर 1.5.1
  • लेनिंगन 2.1.3
  • JDK 1.7.0 अपडेट 25

क्लोजर भाग

पहले लेनिंगेन का उपयोग करके एक परियोजना और संबंधित निर्देशिका संरचना बनाएं:

C:\projects>lein new com.domain.tiny

अब, प्रोजेक्ट डायरेक्टरी में बदलाव करें।

C:\projects>cd com.domain.tiny

प्रोजेक्ट डायरेक्टरी में, project.cljफ़ाइल खोलें और इसे इस तरह संपादित करें कि सामग्री नीचे दिखाए गए अनुसार हो।

(defproject com.domain.tiny "0.1.0-SNAPSHOT"
  :description "An example of stand alone Clojure-Java interop"
  :url "http://clarkonium.net/2013/06/java-clojure-interop-an-update/"
  :license {:name "Eclipse Public License"
  :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]]
  :aot :all
  :main com.domain.tiny)

अब, सुनिश्चित करें कि सभी निर्भरताएं (क्लोर्ज) उपलब्ध हैं।

C:\projects\com.domain.tiny>lein deps

आप इस बिंदु पर क्लोजर जार को डाउनलोड करने के बारे में एक संदेश देख सकते हैं।

अब Clojure फ़ाइल को C:\projects\com.domain.tiny\src\com\domain\tiny.cljऐसे संपादित करें कि इसमें मूल उत्तर में दिखाया गया Clojure प्रोग्राम हो। (यह फ़ाइल तब बनाई गई थी जब लेनिंगन ने परियोजना बनाई थी।)

यहां ज्यादातर जादू नाम स्थान की घोषणा में है। :gen-classएक वर्ग के नाम पर रखा गया बनाने के लिए प्रणाली बताता com.domain.tinyनामक केवल एक स्थिर विधि के साथ binomial, एक समारोह दो पूर्णांक तर्क ले रहे हैं और एक डबल लौटने। दो समान नाम वाले कार्य हैं binomial, एक पारंपरिक क्लोजर फ़ंक्शन और -binomialजावा से सुलभ रैपर। फ़ंक्शन नाम में हाइफ़न पर ध्यान दें -binomial। डिफ़ॉल्ट उपसर्ग एक हाइफ़न है, लेकिन इसे वांछित होने पर इसे किसी और चीज़ में बदला जा सकता है। -mainसमारोह सिर्फ द्विपद समारोह के लिए कॉल की एक जोड़ी को आश्वस्त करने के कि हम सही परिणाम दे रहे हैं बनाता है। ऐसा करने के लिए, कक्षा को संकलित करें और कार्यक्रम चलाएं।

C:\projects\com.domain.tiny>lein run

आपको मूल उत्तर में दिखाए गए आउटपुट को देखना चाहिए।

अब इसे एक जार में पैकेज करें और इसे कहीं भी सुविधाजनक रखें। क्लोजर जार को भी वहां कॉपी करें।

C:\projects\com.domain.tiny>lein jar
Created C:\projects\com.domain.tiny\target\com.domain.tiny-0.1.0-SNAPSHOT.jar
C:\projects\com.domain.tiny>mkdir \target\lib

C:\projects\com.domain.tiny>copy target\com.domain.tiny-0.1.0-SNAPSHOT.jar target\lib\
        1 file(s) copied.

C:\projects\com.domain.tiny>copy "C:<path to clojure jar>\clojure-1.5.1.jar" target\lib\
        1 file(s) copied.

जावा भाग

लेनिंगन का एक अंतर्निहित कार्य है, lein-javacजो जावा संकलन के साथ मदद करने में सक्षम होना चाहिए। दुर्भाग्य से, यह 2.1.3 संस्करण में टूट गया है। यह JDK स्थापित नहीं कर सकता है और यह Maven रिपॉजिटरी नहीं खोज सकता है। दोनों के रास्तों में मेरे सिस्टम पर जगह खाली है। मैं मानता हूं कि यही समस्या है। कोई भी जावा आईडीई संकलन और पैकेजिंग को संभाल सकता है। लेकिन इस पोस्ट के लिए, हम पुराने स्कूल जा रहे हैं और इसे कमांड लाइन पर कर रहे हैं।

पहले Main.javaमूल उत्तर में दिखाई गई सामग्री के साथ फाइल बनाएं ।

जावा भाग संकलित करने के लिए

javac -g -cp target\com.domain.tiny-0.1.0-SNAPSHOT.jar -d target\src\com\domain\Main.java

अब हमारे द्वारा बनाए गए जार में जोड़ने के लिए कुछ मेटा-जानकारी के साथ एक फ़ाइल बनाएं। में Manifest.txt, निम्न पाठ जोड़ें

Class-Path: lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
Main-Class: Main

अब इसे सभी एक बड़े जार फ़ाइल में पैकेज करें, जिसमें हमारे क्लोजर प्रोग्राम और क्लोजर जार शामिल हैं।

C:\projects\com.domain.tiny\target>jar cfm Interop.jar Manifest.txt Main.class lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar

कार्यक्रम चलाने के लिए:

C:\projects\com.domain.tiny\target>java -jar Interop.jar
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263

उत्पादन अनिवार्य रूप से अकेले क्लोजर द्वारा उत्पादित के समान है, लेकिन परिणाम जावा डबल में बदल दिया गया है।

जैसा कि उल्लेख किया गया है, एक जावा आईडीई शायद गड़बड़ संकलन तर्क और पैकेजिंग का ख्याल रखेगा।


4
1. क्या मैं आपके उदाहरण को clojuredocs.org पर "ns" मैक्रो के उदाहरण के रूप में रख सकता हूँ ? 2. ":" विधियों के सामने # ^ क्या है [# ^ {: स्थिर सत्य} [द्विपद [इंट इंट] डबल]] "(मैं एक नौसिखिया हूँ)?
बेलुण

5
@ बेलुन, यकीन है कि आप इसे एक उदाहरण के रूप में उपयोग कर सकते हैं - मैं चापलूसी कर रहा हूं। "# ^ {: Static true}" फ़ंक्शन को कुछ मेटाडेटा देता है जो दर्शाता है कि द्विपद एक स्थिर फ़ंक्शन है। इस मामले में इसकी आवश्यकता है क्योंकि, जावा पक्ष पर, हम फ़ंक्शन को मुख्य से बुला रहे हैं - एक स्थिर फ़ंक्शन। यदि द्विपद स्थिर नहीं थे, तो जावा पक्ष पर मुख्य फ़ंक्शन को संकलित करने से "गैर-स्थैतिक विधि द्विपद (int, int) के बारे में एक त्रुटि संदेश उत्पन्न होगा जो स्थैतिक संदर्भ से संदर्भित नहीं किया जा सकता है"। ऑब्जेक्ट मेंटर साइट पर अतिरिक्त उदाहरण हैं।
क्लार्कट

4
यहाँ एक महत्वपूर्ण बात का उल्लेख नहीं किया गया है - जावा क्लास में क्लोजर फाइल संकलित करने के लिए, आपको इसकी आवश्यकता है: (संकलन 'com.domain.tiny)
डोमची

आप एओएल क्लोजर स्रोत का संकलन कैसे कर रहे हैं? यह वह जगह है जहां मैं फंस गया हूं।
मैथ्यू बोस्टन

@MatthewBoston जिस समय उत्तर लिखा गया था, मैंने नेटब्लिज आईडीई के लिए एक प्लगइन एनक्लोजुरे का उपयोग किया था। अब, मैं शायद लेनिंगन का उपयोग करूंगा, लेकिन इसकी कोशिश या परीक्षण नहीं किया है।
क्लर्कट

119

क्लोजर 1.6.0 के रूप में, क्लोजर कार्यों को लोड और आह्वान करने का एक नया पसंदीदा तरीका है। इस पद्धति को अब सीधे आरटी को कॉल करने के लिए पसंद किया जाता है (और यहां कई अन्य उत्तरों को सुपरसीड किया जाता है)। जावदोक यहाँ है - मुख्य प्रवेश बिंदु है clojure.java.api.Clojure

क्लोजर फ़ंक्शन को देखने और कॉल करने के लिए:

IFn plus = Clojure.var("clojure.core", "+");
plus.invoke(1, 2);

कार्य में clojure.coreस्वचालित रूप से भरी हुई हैं। अन्य नामस्थान आवश्यकता के माध्यम से लोड किए जा सकते हैं:

IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("clojure.set"));

IFnरों उच्च आदेश कार्यों के लिए पारित किया जा सकता, गुजरता नीचे दिए गए उदाहरण जैसे plusकरने के लिए read:

IFn map = Clojure.var("clojure.core", "map");
IFn inc = Clojure.var("clojure.core", "inc");
map.invoke(inc, Clojure.read("[1 2 3]"));

IFnक्लोजर में अधिकांश एस कार्यों का उल्लेख करते हैं। कुछ, हालांकि, गैर-फ़ंक्शन डेटा मानों को देखें। इन्हें एक्सेस करने के लिए, derefइसके बजाय का उपयोग करें fn:

IFn printLength = Clojure.var("clojure.core", "*print-length*");
IFn deref = Clojure.var("clojure.core", "deref");
deref.invoke(printLength);

कभी-कभी (अगर क्लोजर रनटाइम के कुछ अन्य भाग का उपयोग करते हुए), तो आपको यह सुनिश्चित करने की आवश्यकता हो सकती है कि क्लोजर रनटाइम को ठीक से आरंभीकृत किया गया है - क्लोजर वर्ग पर एक विधि को कॉल करना इस उद्देश्य के लिए पर्याप्त है। यदि आपको क्लॉजुर पर एक विधि को कॉल करने की आवश्यकता नहीं है, तो बस वर्ग को लोड करने के लिए पर्याप्त है (अतीत में आरटी वर्ग को लोड करने के लिए एक समान सिफारिश की गई है; यह अब पसंद किया जाता है):

Class.forName("clojure.java.api.Clojure") 

1
इस दृष्टिकोण का उपयोग करते हुए, स्क्रिप्ट उद्धरण का उपयोग नहीं कर सकती है () और चीजों की आवश्यकता होती है। क्या इसका कोई हल है?
रेनाटो

2
मुझे लगता है कि केवल कुछ विशेष रूप हैं जो var के रूप में भी मौजूद नहीं हैं। एक वर्कअराउंड के माध्यम से इसे एक्सेस करना है Clojure.read("'(1 2 3")। यह एक एन्हांसमेंट रिक्वेस्ट के रूप में दायर करना उचित होगा, हालांकि क्लोजर.क्वाटे () प्रदान करने के लिए या इसे एक संस्करण के रूप में काम करके।
एलेक्स मिलर

1
@ रेनाटो को कुछ भी उद्धृत करने की कोई आवश्यकता नहीं है, क्योंकि कुछ भी वैसे भी क्लूज्योर के मूल्यांकन नियमों द्वारा मूल्यांकन नहीं किया जा रहा है। यदि आप 1-3 की संख्या वाली सूची चाहते हैं, तो लिखने के बजाय '(1 2 3)आप कुछ ऐसा लिखें Clojure.var("clojure.core", "list").invoke(1,2,3)। और जवाब पहले से ही उपयोग करने के तरीके का एक उदाहरण है require: यह किसी भी अन्य की तरह सिर्फ एक संस्करण है।
अमलौस

34

EDIT यह उत्तर 2010 में लिखा गया था, और उस समय काम किया था। अधिक आधुनिक समाधान के लिए एलेक्स मिलर का जवाब देखें।

जावा से किस तरह के कोड कह रहे हैं? यदि आपके पास जीन-क्लास के साथ उत्पन्न वर्ग है, तो बस इसे कॉल करें। यदि आप स्क्रिप्ट से फ़ंक्शन को कॉल करना चाहते हैं, तो निम्न उदाहरण देखें

यदि आप Java के अंदर स्ट्रिंग से कोड का मूल्यांकन करना चाहते हैं, तो आप निम्नलिखित कोड का उपयोग कर सकते हैं:

import clojure.lang.RT;
import clojure.lang.Var;
import clojure.lang.Compiler;
import java.io.StringReader;

public class Foo {
  public static void main(String[] args) throws Exception {
    // Load the Clojure script -- as a side effect this initializes the runtime.
    String str = "(ns user) (defn foo [a b]   (str a \" \" b))";

    //RT.loadResourceScript("foo.clj");
    Compiler.load(new StringReader(str));

    // Get a reference to the foo function.
    Var foo = RT.var("user", "foo");

    // Call it!
    Object result = foo.invoke("Hi", "there");
    System.out.println(result);
  }
}

1
यदि आप नाम स्थान (यानी (मेरा -10 संस्करण को ख़त्म करना) का उपयोग करना चाहते हैं तो थोड़ा विस्तार करने के लिए इसका उपयोग करें RT.var("namespace", "my-var").deref()
इवान कोबलिक

यह RT.load("clojure/core");शुरुआत में जोड़े बिना मेरे लिए काम नहीं करता है । क्या अजीब व्यवहार है?
hestestupin

यह काम करता है और मेरे द्वारा उपयोग किए जा रहे समान है; यकीन नहीं है कि यह सबसे नई तकनीक है। मैं क्लोजर 1.4 या 1.6 का उपयोग कर सकता हूं, निश्चित नहीं।
यान राजा यिन

12

EDIT: मैंने यह उत्तर लगभग तीन साल पहले लिखा था। Clojure 1.6 में जावा से Clojure को कॉल करने के उद्देश्य से एक उचित API है। कृपया जानकारी के लिए एलेक्स मिलर का जवाब दें

2011 से मूल उत्तर:

जैसा कि मैंने देखा है, सरल तरीका (यदि आप एओटी संकलन के साथ एक वर्ग उत्पन्न नहीं करते हैं) तो क्लोजर में कार्यों तक पहुंचने के लिए clojure.lang.RT का उपयोग करना है। इसके साथ आप यह स्पष्ट कर सकते हैं कि आपने क्लोजर में क्या किया होगा (विशेष तरीकों से चीजों को संकलित करने की आवश्यकता नहीं है):

;; Example usage of the "bar-fn" function from the "foo.ns" namespace from Clojure
(require 'foo.ns)
(foo.ns/bar-fn 1 2 3)

और जावा में:

// Example usage of the "bar-fn" function from the "foo.ns" namespace from Java
import clojure.lang.RT;
import clojure.lang.Symbol;
...
RT.var("clojure.core", "require").invoke(Symbol.intern("foo.ns"));
RT.var("foo.ns", "bar-fn").invoke(1, 2, 3);

यह जावा में थोड़ी अधिक क्रिया है, लेकिन मुझे आशा है कि यह स्पष्ट है कि कोड के टुकड़े बराबर हैं।

यह तब तक काम करना चाहिए जब तक कि क्लोजर पर क्लोजर और आपके क्लोजर कोड के स्रोत फाइल (या संकलित फाइलें) हों।


1
यह सलाह क्लोजर 1.6 के रूप में पुरानी है - कृपया इसके बजाय clojure.java.api.Clojure का उपयोग करें।
एलेक्स मिलर

नहीं समय में एक बुरा जवाब है, लेकिन मैं इनाम के लिए होती stackoverflow.com/a/23555959/1756702 Clojure 1.6 के लिए आधिकारिक जवाब के रूप में। कल फिर कोशिश करेंगे ...
ए। वेब

एलेक्स का जवाब वास्तव में इनाम का हकदार है! कृपया मुझे बताएं कि क्या जरूरत पड़ने पर मैं इनाम को स्थानांतरित करने में मदद कर सकता हूं।
raek

@ मेरा मन नहीं है कि आपको मेरी ओवर-कैफ़िनेटेड ट्रिगर फिंगर से थोड़ा सा बोनस मिला। आशा है कि आप फिर से क्लोजर टैग के आसपास देख पाएंगे।
ए। वेब

10

मैं क्लार्कट के उत्तर से सहमत हूं, लेकिन मुझे लगा कि शुरुआती लोग भी इसका उपयोग कर सकते हैं:

  • चरण-दर-चरण जानकारी वास्तव में यह कैसे चल रही है
  • जानकारी जो क्लोजर 1.3 और लेनिंगेन के हाल के संस्करणों के लिए वर्तमान है।
  • एक क्लोजर जार जिसमें एक मुख्य कार्य भी शामिल है, इसलिए इसे स्टैंडअलोन चलाया जा सकता है या लाइब्रेरी के रूप में जोड़ा जा सकता है ।

इसलिए मैंने इस ब्लॉग पोस्ट में वह सब शामिल किया ।

क्लोजर कोड इस तरह दिखता है:

(ns ThingOne.core
 (:gen-class
    :methods [#^{:static true} [foo [int] void]]))

(defn -foo [i] (println "Hello from Clojure. My input was " i))

(defn -main [] (println "Hello from Clojure -main." ))

Leiningen 1.7.1 परियोजना सेटअप इस तरह दिखता है:

(defproject ThingOne "1.0.0-SNAPSHOT"
  :description "Hello, Clojure"
  :dependencies [[org.clojure/clojure "1.3.0"]]
  :aot [ThingOne.core]
  :main ThingOne.core)

जावा कोड इस तरह दिखता है:

import ThingOne.*;

class HelloJava {
    public static void main(String[] args) {
        System.out.println("Hello from Java!");
        core.foo (12345);
    }
}

या आप इस प्रोजेक्ट के सभी कोड भी जीथब पर प्राप्त कर सकते हैं ।


आपने एओटी का उपयोग क्यों किया? क्या यह कार्यक्रम को प्लेटफ़ॉर्म-इंडिपेटेट नहीं होने देता है?
एडवर्ड

3

यह क्लोजर 1.5.0 के साथ काम करता है:

public class CljTest {
    public static Object evalClj(String a) {
        return clojure.lang.Compiler.load(new java.io.StringReader(a));
    }

    public static void main(String[] args) {
        new clojure.lang.RT(); // needed since 1.5.0        
        System.out.println(evalClj("(+ 1 2)"));
    }
}

2

यदि उपयोग का मामला एक जावा एप्लिकेशन में क्लोजर के साथ निर्मित एक जार को शामिल करने के लिए है, तो मैंने पाया है कि दोनों दुनियाओं के बीच इंटरफेस के लिए एक अलग नामस्थान होना फायदेमंद है:

(ns example-app.interop
  (:require [example-app.core :as core])

;; This example covers two-way communication: the Clojure library 
;; relies on the wrapping Java app for some functionality (through
;; an interface that the Clojure library provides and the Java app
;; implements) and the Java app calls the Clojure library to perform 
;; work. The latter case is covered by a class provided by the Clojure lib.
;; 
;; This namespace should be AOT compiled.

;; The interface that the java app can implement
(gen-interface
  :name com.example.WeatherForecast
  :methods [[getTemperature [] Double]])

;; The class that the java app instantiates
(gen-class
  :name com.example.HighTemperatureMailer
  :state state
  :init init
  ;; Dependency injection - take an instance of the previously defined
  ;; interface as a constructor argument
  :constructors {[com.example.WeatherForecast] []}
  :methods [[sendMails [] void]])

(defn -init [weather-forecast]
  [[] {:weather-forecast weather-forecast}])

;; The actual work is done in the core namespace
(defn -sendMails
  [this]
  (core/send-mails (.state this)))

मुख्य नाम स्थान अपने कार्यों को पूरा करने के लिए इंजेक्ट किए गए उदाहरण का उपयोग कर सकते हैं:

(ns example-app.core)

(defn send-mails 
  [{:keys [weather-forecast]}]
  (let [temp (.getTemperature weather-forecast)] ...)) 

परीक्षण उद्देश्यों के लिए, इंटरफ़ेस को स्टब किया जा सकता है:

(example-app.core/send-mails 
  (reify com.example.WeatherForecast (getTemperature [this] ...)))

0

जेवीएम के शीर्ष पर अन्य भाषाओं के साथ काम करने वाली अन्य तकनीक उन कार्यों के लिए एक इंटरफ़ेस घोषित करना है जिन्हें आप कॉल करना चाहते हैं और फिर 'प्रॉक्सी' फ़ंक्शन का उपयोग करके उदाहरण के लिए उन्हें लागू करते हैं।


-1

आप अपने क्लोजर कोड का प्रतिनिधित्व करने वाली वर्ग फ़ाइलों को बनाने के लिए एओटी संकलन का भी उपयोग कर सकते हैं। यह कैसे करें के बारे में विवरण के लिए क्लोजर एपीआई डॉक्स में संकलन, जीन-क्लास और दोस्तों के बारे में प्रलेखन पढ़ें, लेकिन संक्षेप में आप एक वर्ग बनाएंगे जो प्रत्येक पद्धति के आह्वान के लिए क्लोजर फ़ंक्शन को कॉल करता है।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.