सी ++ में लैम्ब्डा अभिव्यक्तियां

Lambda Expressions C



लैम्ब्डा अभिव्यक्ति क्यों?

निम्नलिखित कथन पर विचार करें:

NSमींट= 52;

यहाँ, myInt एक पहचानकर्ता है, एक अंतराल है। ५२ एक शाब्दिक, एक प्रचलन है। आज, किसी फ़ंक्शन को विशेष रूप से कोड करना और उसे 52 की स्थिति में रखना संभव है। इस तरह के फ़ंक्शन को लैम्ब्डा एक्सप्रेशन कहा जाता है। निम्नलिखित लघु कार्यक्रम पर भी विचार करें:







#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

NSएफएन(NSके माध्यम से)

{

NSउत्तर=के माध्यम से+ 3;

वापसीउत्तर;

}


NSमुख्य()

{

एफएन(5);



वापसी 0;

}

आज, किसी फ़ंक्शन को विशेष रूप से कोड करना और फ़ंक्शन कॉल, fn(5) के 5 के तर्क की स्थिति में रखना संभव है। ऐसे फ़ंक्शन को लैम्ब्डा एक्सप्रेशन कहा जाता है। उस स्थिति में लैम्ब्डा अभिव्यक्ति (फ़ंक्शन) एक प्रचलित है।



स्ट्रिंग अक्षर को छोड़कर कोई भी शाब्दिक एक प्रचलित है। लैम्ब्डा एक्सप्रेशन एक विशेष फ़ंक्शन डिज़ाइन है जो कोड में एक शाब्दिक के रूप में फिट होगा। यह एक अनाम (अनाम) फ़ंक्शन है। यह आलेख लैम्ब्डा अभिव्यक्ति नामक नई सी ++ प्राथमिक अभिव्यक्ति की व्याख्या करता है। इस लेख को समझने के लिए C++ में बुनियादी ज्ञान की आवश्यकता है।



लेख सामग्री

लैम्ब्डा अभिव्यक्ति का चित्रण

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





#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

ऑटोएफएन= [](NSविराम)

{

NSउत्तर=विराम+ 3;

वापसीउत्तर;

};


NSमुख्य()

{

ऑटोचरबी=एफएन(2);

लागत <<चरबी<< 'एन';


वापसी 0;

}

आउटपुट है:

5

मुख्य () फ़ंक्शन के बाहर, चर है, fn। इसका प्रकार ऑटो है। इस स्थिति में ऑटो का मतलब है कि वास्तविक प्रकार, जैसे कि इंट या फ्लोट, असाइनमेंट ऑपरेटर (=) के सही ऑपरेंड द्वारा निर्धारित किया जाता है। असाइनमेंट ऑपरेटर के दाईं ओर लैम्ब्डा एक्सप्रेशन है। लैम्ब्डा अभिव्यक्ति पिछले रिटर्न प्रकार के बिना एक फ़ंक्शन है। वर्ग कोष्ठकों के उपयोग और स्थिति पर ध्यान दें, []। फ़ंक्शन 5 देता है, एक int, जो fn के प्रकार को निर्धारित करेगा।



मुख्य () फ़ंक्शन में, कथन है:

ऑटोचरबी=एफएन(2);

इसका मतलब है, मुख्य () के बाहर fn, किसी फ़ंक्शन के पहचानकर्ता के रूप में समाप्त होता है। इसके निहित पैरामीटर लैम्ब्डा अभिव्यक्ति के हैं। variab के लिए प्रकार ऑटो है।

ध्यान दें कि लैम्ब्डा अभिव्यक्ति अर्धविराम के साथ समाप्त होती है, जैसे वर्ग या संरचना परिभाषा, अर्धविराम के साथ समाप्त होती है।

निम्नलिखित कार्यक्रम में, एक फ़ंक्शन, जो एक लैम्ब्डा अभिव्यक्ति है जो 5 का मान लौटाता है, दूसरे फ़ंक्शन के लिए एक तर्क है:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

शून्यअन्य एफएन(NSनंबर 1,NS (*पीटीआर)(NS))

{

NSनंबर 2= (*पीटीआर)(2);

लागत <<नं .1<< '' <<नंबर 2<< 'एन';

}


NSमुख्य()

{

अन्य एफएन(4,[](NSविराम)

{

NSउत्तर=विराम+ 3;

वापसीउत्तर;

});


वापसी 0;
}

आउटपुट है:

चार पांच

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

अन्य एफएन () फ़ंक्शन की परिभाषा में लैम्ब्डा फ़ंक्शन पैरामीटर फ़ंक्शन के लिए एक सूचक है। सूचक का नाम ptr है। लैम्ब्डा फ़ंक्शन को कॉल करने के लिए नाम, पीटीआर, अन्य एफएन () परिभाषा में उपयोग किया जाता है।

बयान,

NSनंबर 2= (*पीटीआर)(2);

अन्य एफएन () परिभाषा में, यह लैम्ब्डा फ़ंक्शन को 2 के तर्क के साथ कॉल करता है। लैम्ब्डा फ़ंक्शन से कॉल का रिटर्न वैल्यू, '(*ptr)(2)' नंबर 2 को सौंपा गया है।

उपरोक्त कार्यक्रम यह भी दिखाता है कि लैम्ब्डा फ़ंक्शन का उपयोग C++ कॉलबैक फ़ंक्शन योजना में कैसे किया जा सकता है।

लैम्ब्डा अभिव्यक्ति के भाग

एक विशिष्ट लैम्ब्डा फ़ंक्शन के भाग इस प्रकार हैं:

[] () {}
  • [] कैप्चर क्लॉज है। इसमें आइटम हो सकते हैं।
  • () पैरामीटर सूची के लिए है।
  • {} फंक्शन बॉडी के लिए है। यदि फ़ंक्शन अकेला खड़ा है, तो उसे अर्धविराम से समाप्त होना चाहिए।

कैप्चर

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

लैम्ब्डा फ़ंक्शन परिभाषा सामान्य फ़ंक्शन परिभाषा से अलग है। इसे वैश्विक दायरे में एक चर को सौंपा जा सकता है; इस फ़ंक्शन-असाइन-टू-वेरिएबल को किसी अन्य फ़ंक्शन के अंदर भी कोड किया जा सकता है। जब एक वैश्विक स्कोप वैरिएबल को असाइन किया जाता है, तो इसका बॉडी ग्लोबल स्कोप में अन्य वेरिएबल देख सकता है। जब एक सामान्य फ़ंक्शन परिभाषा के अंदर एक चर को सौंपा जाता है, तो उसका शरीर केवल कैप्चर क्लॉज की मदद से फ़ंक्शन स्कोप में अन्य चर देख सकता है, []।

कैप्चर क्लॉज [], जिसे लैम्ब्डा-इंट्रोड्यूसर के रूप में भी जाना जाता है, चर को लैम्ब्डा एक्सप्रेशन के फंक्शन बॉडी में आसपास (फ़ंक्शन) स्कोप से भेजने की अनुमति देता है। लैम्ब्डा एक्सप्रेशन के फंक्शन बॉडी को ऑब्जेक्ट प्राप्त होने पर वेरिएबल को कैप्चर करने के लिए कहा जाता है। कैप्चर क्लॉज [] के बिना, एक वैरिएबल को लैम्ब्डा एक्सप्रेशन के फंक्शन बॉडी में आसपास के दायरे से नहीं भेजा जा सकता है। निम्नलिखित कार्यक्रम इसे मुख्य () फ़ंक्शन स्कोप के साथ, आसपास के दायरे के रूप में दिखाता है:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

NSमुख्य()

{

NSपहचान= 5;


ऑटोएफएन= [पहचान]()

{

लागत <<पहचान<< 'एन';

};

एफएन();


वापसी 0;

}

आउटपुट है 5 . नाम, आईडी के बिना, [] के अंदर, लैम्ब्डा एक्सप्रेशन ने मुख्य () फ़ंक्शन स्कोप की चर आईडी नहीं देखी होगी।

संदर्भ द्वारा कब्जा

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

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

NSमुख्य()

{

NSपहचान= 5; पानी पर तैरनाफुट= २.३; charचौधरी= 'प्रति';

ऑटोएफएन= [औरपहचान,औरफुट,औरचौधरी]()

{

पहचान= 6;फुट= ३.४;चौधरी= 'बी';

};

एफएन();

लागत <<पहचान<< ',' <<फुट<< ',' <<चौधरी<< 'एन';

वापसी 0;

}

आउटपुट है:

6, 3.4, बी

यह पुष्टि करना कि लैम्ब्डा एक्सप्रेशन के फंक्शन बॉडी के अंदर वेरिएबल नाम लैम्ब्डा एक्सप्रेशन के बाहर समान वेरिएबल के लिए हैं।

मूल्य द्वारा कब्जा

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

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

NSमुख्य()

{

NSपहचान= 5; पानी पर तैरनाफुट= २.३; charचौधरी= 'प्रति';

ऑटोएफएन= [आईडी, फीट, चो]()

{

// आईडी = 6; फीट = ३.४; सीएच = 'बी';

लागत <<पहचान<< ',' <<फुट<< ',' <<चौधरी<< 'एन';

};

एफएन();

पहचान= 6;फुट= ३.४;चौधरी= 'बी';

लागत <<पहचान<< ',' <<फुट<< ',' <<चौधरी<< 'एन';

वापसी 0;

}

आउटपुट है:

5, 2.3, ए

6, 3.4, बी

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

मिक्सिंग कैप्चर

संदर्भ द्वारा कैप्चर करना और मूल्य द्वारा कैप्चर करना मिश्रित किया जा सकता है, जैसा कि निम्न प्रोग्राम दिखाता है:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

NSमुख्य()

{

NSपहचान= 5; पानी पर तैरनाफुट= २.३; charचौधरी= 'प्रति'; बूलबीएल= सच;


ऑटोएफएन= [आईडी, फुट,औरच,औरबीएल]()

{

चौधरी= 'बी';बीएल= झूठा;

लागत <<पहचान<< ',' <<फुट<< ',' <<चौधरी<< ',' <<बीएल<< 'एन';

};

एफएन();


वापसी 0;

}

आउटपुट है:

5, 2.3, बी, 0

जब सभी पकड़े गए, संदर्भ के अनुसार हैं:

यदि कैप्चर किए जाने वाले सभी चर संदर्भ द्वारा कैप्चर किए जाते हैं, तो कैप्चर क्लॉज में केवल एक & पर्याप्त होगा। निम्नलिखित कार्यक्रम इसे दर्शाता है:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

NSमुख्य()

{

NSपहचान= 5; पानी पर तैरनाफुट= २.३; charचौधरी= 'प्रति'; बूलबीएल= सच;


ऑटोएफएन= [और]()

{

पहचान= 6;फुट= ३.४;चौधरी= 'बी';बीएल= झूठा;

};

एफएन();

लागत <<पहचान<< ',' <<फुट<< ',' <<चौधरी<< ',' <<बीएल<< 'एन';


वापसी 0;

}

आउटपुट है:

6, 3.4, बी, 0

यदि कुछ चर को संदर्भ द्वारा और अन्य को मूल्य द्वारा कैप्चर किया जाना है, तो एक & सभी संदर्भों का प्रतिनिधित्व करेगा, और शेष प्रत्येक से पहले कुछ भी नहीं होगा, जैसा कि निम्नलिखित कार्यक्रम से पता चलता है:

का उपयोग करते हुए नाम स्थानघंटे;

NSमुख्य()

{

NSपहचान= 5; पानी पर तैरनाफुट= २.३; charचौधरी= 'प्रति'; बूलबीएल= सच;


ऑटोएफएन= [और, आईडी, फीट]()

{

चौधरी= 'बी';बीएल= झूठा;

लागत <<पहचान<< ',' <<फुट<< ',' <<चौधरी<< ',' <<बीएल<< 'एन';

};

एफएन();


वापसी 0;

}

आउटपुट है:

5, 2.3, बी, 0

ध्यान दें कि & अकेले (यानी, पहचानकर्ता द्वारा पीछा नहीं किया गया) कैप्चर क्लॉज में पहला अक्षर होना चाहिए।

जब सभी पर कब्जा कर लिया जाता है, तो मूल्य के अनुसार होते हैं:

यदि कैप्चर किए जाने वाले सभी वेरिएबल्स को वैल्यू द्वारा कैप्चर किया जाना है, तो कैप्चर क्लॉज में सिर्फ एक = पर्याप्त होगा। निम्नलिखित कार्यक्रम इसे दर्शाता है:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

NSमुख्य()
{

NSपहचान= 5; पानी पर तैरनाफुट= २.३; charचौधरी= 'प्रति'; बूलबीएल= सच;


ऑटोएफएन= [=]()

{

लागत <<पहचान<< ',' <<फुट<< ',' <<चौधरी<< ',' <<बीएल<< 'एन';

};

एफएन();


वापसी 0;


}

आउटपुट है:

5, 2.3, ए, 1

ध्यान दें : = अभी केवल पढ़ने के लिए है।

यदि कुछ चरों को मूल्य द्वारा और अन्य को संदर्भ द्वारा कैप्चर किया जाना है, तो एक = सभी केवल-पढ़ने के लिए कॉपी किए गए चर का प्रतिनिधित्व करेगा, और शेष प्रत्येक के पास होगा, जैसा कि निम्नलिखित कार्यक्रम दिखाता है:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

NSमुख्य()

{

NSपहचान= 5; पानी पर तैरनाफुट= २.३; charचौधरी= 'प्रति'; बूलबीएल= सच;


ऑटोएफएन= [=,औरच,औरबीएल]()

{

चौधरी= 'बी';बीएल= झूठा;

लागत <<पहचान<< ',' <<फुट<< ',' <<चौधरी<< ',' <<बीएल<< 'एन';

};

एफएन();


वापसी 0;

}

आउटपुट है:

5, 2.3, बी, 0

ध्यान दें कि = अकेले को कैप्चर क्लॉज में पहला अक्षर होना चाहिए।

लैम्ब्डा एक्सप्रेशन के साथ क्लासिकल कॉलबैक फंक्शन स्कीम

निम्नलिखित कार्यक्रम दिखाता है कि लैम्ब्डा अभिव्यक्ति के साथ शास्त्रीय कॉलबैक फ़ंक्शन योजना कैसे की जा सकती है:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

char *उत्पादन;


ऑटोसीबीए= [](charबाहर[])

{

उत्पादन=बाहर;

};



शून्यमुख्य समारोह(charइनपुट[],शून्य (*के लिये)(char[]))

{

(*के लिये)(इनपुट);

लागत<<'प्रमुख समारोह के लिए'<<'एन';

}


शून्यएफएन()

{

लागत<<'अभी'<<'एन';

}


NSमुख्य()

{

charइनपुट[] = 'कॉलबैक फ़ंक्शन के लिए';

मुख्य समारोह(इनपुट, सीबीए);

एफएन();

लागत<<उत्पादन<<'एन';



वापसी 0;

}

आउटपुट है:

मुख्य समारोह के लिए

अभी

कॉलबैक फ़ंक्शन के लिए

याद रखें कि जब लैम्ब्डा एक्सप्रेशन डेफिनिशन को ग्लोबल स्कोप में एक वेरिएबल को असाइन किया जाता है, तो इसका फंक्शन बॉडी कैप्चर क्लॉज को नियोजित किए बिना ग्लोबल वेरिएबल्स को देख सकता है।

अनुगामी-वापसी-प्रकार

लैम्ब्डा एक्सप्रेशन का रिटर्न प्रकार ऑटो है, जिसका अर्थ है कि कंपाइलर रिटर्न एक्सप्रेशन (यदि मौजूद है) से रिटर्न टाइप निर्धारित करता है। यदि प्रोग्रामर वास्तव में रिटर्न प्रकार को इंगित करना चाहता है, तो वह इसे निम्नलिखित कार्यक्रम की तरह करेगा:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

ऑटोएफएन= [](NSविराम) -> NS

{

NSउत्तर=विराम+ 3;

वापसीउत्तर;

};


NSमुख्य()

{

ऑटोचरबी=एफएन(2);

लागत <<चरबी<< 'एन';


वापसी 0;

}

आउटपुट 5 है। पैरामीटर सूची के बाद, एरो ऑपरेटर टाइप किया जाता है। इसके बाद रिटर्न टाइप (इस मामले में int) आता है।

समापन

निम्नलिखित कोड खंड पर विचार करें:

structक्लास

{

NSपहचान= 5;

charचौधरी= 'प्रति';

}obj1, obj2;

यहाँ, Cla संरचना वर्ग का नाम है। Obj1 और obj2 दो ऑब्जेक्ट हैं जिन्हें स्ट्रक्चर क्लास से इंस्टेंट किया जाएगा। लैम्ब्डा अभिव्यक्ति कार्यान्वयन में समान है। लैम्ब्डा फ़ंक्शन परिभाषा एक प्रकार का वर्ग है। जब लैम्ब्डा फ़ंक्शन को (आह्वान) कहा जाता है, तो किसी ऑब्जेक्ट को उसकी परिभाषा से तत्काल किया जाता है। इस वस्तु को बंद कहा जाता है। यह वह बंद है जो लैम्ब्डा से अपेक्षित कार्य करता है।

हालाँकि, लैम्ब्डा एक्सप्रेशन को ऊपर दिए गए स्ट्रक्चर की तरह कोडिंग में obj1 और obj2 को संबंधित पैरामीटर्स के तर्कों से बदल दिया जाएगा। निम्नलिखित कार्यक्रम इसे दर्शाता है:

#शामिल

का उपयोग करते हुए नाम स्थानघंटे;

ऑटोएफएन= [](NSparam1,NSपरम २)

{

NSउत्तर=param1+परम २;

वापसीउत्तर;

} (2,3);


NSमुख्य()

{

ऑटोकहां=एफएन;

लागत <<कहां<< 'एन';


वापसी 0;

}

आउटपुट 5 है। तर्क कोष्ठक में 2 और 3 हैं। ध्यान दें कि लैम्ब्डा एक्सप्रेशन फ़ंक्शन कॉल, fn, कोई तर्क नहीं लेता है क्योंकि लैम्ब्डा फ़ंक्शन परिभाषा के अंत में तर्क पहले ही कोडित हो चुके हैं।

निष्कर्ष

लैम्ब्डा अभिव्यक्ति एक अनाम कार्य है। यह दो भागों में है: वर्ग और वस्तु। इसकी परिभाषा एक प्रकार का वर्ग है। जब व्यंजक कहा जाता है, तो परिभाषा से एक वस्तु का निर्माण होता है। इस वस्तु को बंद कहा जाता है। यह वह बंद है जो लैम्ब्डा से अपेक्षित कार्य करता है।

लैम्ब्डा अभिव्यक्ति के लिए बाहरी फ़ंक्शन स्कोप से एक चर प्राप्त करने के लिए, इसे अपने फ़ंक्शन बॉडी में एक गैर-रिक्त कैप्चर क्लॉज की आवश्यकता होती है।