जावा 8 में 2 तीरों के साथ लैम्ब्डा का क्या अर्थ है?


118

मैंने पहले कई जावा 8 ट्यूटोरियल पढ़े हैं।

अभी मुझे निम्नलिखित विषय का सामना करना पड़ा है: क्या जावा करी का समर्थन करता है?

यहाँ, मैं निम्नलिखित कोड देखता हूं:

IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));

मैं समझता हूं कि इस उदाहरण में २ तत्व हैं लेकिन मैं निर्माण को नहीं समझ सकता:

a -> b -> a + b;

अभिव्यक्ति के बाएं हिस्से के अनुसार, इस पंक्ति को निम्नलिखित फ़ंक्शन को लागू करना चाहिए:

R apply(int value); 

इससे पहले, मैं केवल एक तीर से लंबोदर से मिला था।


6
क्या आप समझते हैं कि करी का मतलब क्या है? इस सवाल का यह बहुत अभिन्न अंग है।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

12
यह सिर्फ एक मेमना है जो एक मेमना लौटाता है।
इल्मरी करोनन

जवाबों:


118

यदि आप इसे गैर-शॉर्टहैंड लैम्ब्डा सिंटैक्स या प्री-लैम्ब्डा जावा अनाम वर्ग सिंटैक्स के रूप में व्यक्त करते हैं, तो यह स्पष्ट है ...

मूल प्रश्न। दो तीर क्यों हैं? सरल, दो कार्यों को परिभाषित किया जा रहा है ... पहला फ़ंक्शन एक फ़ंक्शन-डिफाइनिंग-फ़ंक्शन है, दूसरा उस फ़ंक्शन का परिणाम है, जो फ़ंक्शन भी होता है। प्रत्येक को ->इसे परिभाषित करने के लिए एक ऑपरेटर की आवश्यकता होती है।

गैर आशुलिपि

IntFunction<IntUnaryOperator> curriedAdd = (a) -> {
    return (b) -> {
        return a + b;
    };
};

जावा 8 से पहले लैंबडा

IntFunction<IntUnaryOperator> curriedAdd = new IntFunction<IntUnaryOperator>() {
    @Override
    public IntUnaryOperator apply(final int value) {
        IntUnaryOperator op = new IntUnaryOperator() {
            @Override
            public int applyAsInt(int operand) {
                return operand + value;
            }
        };
        return op;
    }
};

1
प्री- final int value
लैंबडा

8
हां, आप सही हैं, लेकिन मैंने लिखा है कि अभी भी एक जावा 8 कंपाइलर का उपयोग करके जो आपको "प्रभावी रूप से अंतिम" चीजों का उपयोग करने की अनुमति देता है
एडम

1
@gstackoverflow हाँ, लेकिन तब java 8 नहीं हैpre-lambda
njzk2

1
आप जावा 8 में भी प्री-लैम्बडा स्टाइल का उपयोग कर सकते हैं। मैंने इसे JFY
gstackoverflow

3
क्या लंबोदर ने ऐसा नहीं किया था ताकि एसओ लोग अंक स्कोर कर सकें? :-)
स्टीफन

48

एक IntFunction<R>फ़ंक्शन है int -> R। एक IntUnaryOperatorफ़ंक्शन है int -> int

इस प्रकार IntFunction<IntUnaryOperator>एक फ़ंक्शन है जो एक intपैरामीटर के रूप में लेता है और एक फ़ंक्शन को वापस करता है जो एक intपैरामीटर के रूप में लेता है और एक वापस करता है int

a -> b -> a + b;
^    |         |
|     ---------
|         ^
|         |
|         The IntUnaryOperator (that takes an int, b) and return an int (the sum of a and b)
|
The parameter you give to the IntFunction

हो सकता है कि यह अधिक स्पष्ट हो अगर आप अनाम वर्गों का उपयोग लंबोदर को "विघटित" करने के लिए करते हैं:

IntFunction<IntUnaryOperator> add = new IntFunction<IntUnaryOperator>() {
    @Override
    public IntUnaryOperator apply(int a) {
        return new IntUnaryOperator() {
            @Override
            public int applyAsInt(int b) {
                return a + b;
            }
        };
    }
};

29

कोष्ठक जोड़ने से यह अधिक स्पष्ट हो सकता है:

IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));

या शायद मध्यवर्ती चर मदद कर सकता है:

IntFunction<IntUnaryOperator> curriedAdd = a -> {
    IntUnaryOperator op = b -> a + b;
    return op;
};

24

आइए इसे दोबारा स्पष्ट करने के लिए कोष्ठक के साथ लंबोदर अभिव्यक्ति को फिर से लिखें:

IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));

इसलिए हम एक फंक्शन की घोषणा कर रहे हैं, intजिसमें रिटर्न मिलता है Function। अधिक विशेष रूप से, लौटाया गया फ़ंक्शन ए intऔर रिटर्न देता है int(दो तत्वों का योग): इसे ए के रूप में दर्शाया जा सकता है IntUnaryOperator

इसलिए, curriedAddएक फ़ंक्शन एक है intऔर एक वापस लौट रहा है IntUnaryOperator, इसलिए इसे इस रूप में दर्शाया जा सकता है IntFunction<IntUnaryOperator>


9

यह दो लंबोदर भाव है।

IntFunction<IntUnaryOperator> curriedAdd = 
  a -> { //this is for the fixed value
    return b -> { //this is for the add operation
      return a + b;
    };
  }

IntUnaryOperator addTwo = curriedAdd.apply(2);
System.out.println(addTwo.applyAsInt(12)); //prints 14

8

यदि आप IntFunctionइसे देखते हैं तो यह स्पष्ट हो सकता है: IntFunction<R>एक है FunctionalInterface। यह एक फ़ंक्शन का प्रतिनिधित्व करता है जो एक लेता है intऔर प्रकार का मान लौटाता है R

इस मामले में, वापसी प्रकार Rभी एक है FunctionalInterface, अर्थात् IntUnaryOperator। तो पहला (बाहरी) फ़ंक्शन स्वयं एक फ़ंक्शन देता है।

इस स्थिति में: जब एक पर लागू किया जाता है int, curriedAddतो उस फ़ंक्शन को वापस करने के लिए माना जाता है जो फिर से एक लेता है int(और फिर से लौटता है int, क्योंकि यही वह IntUnaryOperatorकरता है)।

फ़ंक्शनल प्रोग्रामिंग में, किसी फ़ंक्शन के प्रकार को लिखना सामान्य है param -> return_valueऔर आप यहां ठीक उसी तरह देखते हैं। तो का प्रकार curriedAddहै int -> int -> int(या int -> (int -> int)यदि आप इसे बेहतर पसंद करते हैं)।

जावा 8 का लंबोदर सिंटैक्स इसके साथ जाता है। ऐसे फ़ंक्शन को परिभाषित करने के लिए, आप लिखते हैं

a -> b -> a + b

जो वास्तविक लैम्ब्डा कलन के समान है:

λa λb a + b

λb a + bएक ऐसा कार्य है जो एकल पैरामीटर लेता है bऔर एक मान (राशि) लौटाता है। λa λb a + bएक ऐसा कार्य है जो एकल पैरामीटर को स्वीकार करता है aऔर एकल पैरामीटर के दूसरे फ़ंक्शन को लौटाता है। पैरामीटर मान पर सेट के साथ λa λb a + bरिटर्न ।λb a + ba

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