कोई कारण नहीं वैश्विक लैम्ब्डा का उपयोग करने के लिए?


89

हमारे पास एक ऐसा कार्य था जो अपने आप में एक गैर-कैप्चरिंग लैम्ब्डा आंतरिक का उपयोग करता था, जैसे:

void foo() {
  auto bar = [](int a, int b){ return a + b; }

  // code using bar(x,y) a bunch of times
}

अब लैम्ब्डा द्वारा लागू की गई कार्यक्षमता कहीं और आवश्यक हो गई, इसलिए मैं लैम्ब्डा foo()को वैश्विक / नेमस्पेस दायरे से बाहर करने जा रहा हूं । मैं या तो इसे लंबोदर के रूप में छोड़ सकता हूं, इसे कॉपी-पेस्ट विकल्प बना सकता हूं, या इसे एक उचित फ़ंक्शन में बदल सकता हूं:

auto bar = [](int a, int b){ return a + b; } // option 1
int bar(int a, int b){ return a + b; } // option 2

void foo() {
  // code using bar(x,y) a bunch of times
}

इसे एक उचित कार्य में बदलना तुच्छ है, लेकिन यह मुझे आश्चर्यचकित करता है कि क्या कोई कारण है कि इसे लंबोदर के रूप में नहीं छोड़ा जाए? क्या "नियमित" वैश्विक कार्यों के बजाय हर जगह केवल लैम्ब्डा का उपयोग करने का कोई कारण नहीं है?


मुझे लगता है कि अनपेक्षित चर को कैप्चर करने से कई त्रुटियां हो सकती हैं यदि लैम्ब्डा का सावधानीपूर्वक उपयोग नहीं किया जाता है
मैक्रोलैंड

इस के लिए कुछ तर्क youtube.com/watch?v=Ft3zFk7VPrE
sudo rm -rf slash

जवाबों:


61

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

C ++ का नियमित फ़ंक्शन सिंटैक्स आसपास रहा है। सी। प्रोग्रामर के दिनों के बाद से दशकों से जाना जाता है कि वाक्यविन्यास का क्या अर्थ है और वे कैसे काम करते हैं (हालांकि माना जाता है कि संपूर्ण फ़ंक्शन-टू-पॉइंटर क्षय चीज़ कभी-कभी अनुभवी प्रोग्रामर को भी काटती है)। यदि "utter newbie" से परे किसी भी कौशल स्तर का C ++ प्रोग्रामर एक फ़ंक्शन परिभाषा देखता है, तो वे जानते हैं कि उन्हें क्या मिल रहा है।

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

तो अब, आपने अन्य प्रोग्रामर के साथ संवाद स्थापित करने में बार उठाया है। यदि वे यह समझने के लिए जा रहे हैं कि यह फ़ंक्शन क्या कर रहा है तो C ++ प्रोग्रामर को लैम्ब्डा समझने की आवश्यकता है। और हां, यह 2019 है, इसलिए एक सभ्य सी ++ प्रोग्रामर को यह अंदाजा होना चाहिए कि एक लंबोदर कैसा दिखता है। लेकिन यह अभी भी एक उच्च पट्टी है।

और यहां तक ​​कि अगर वे इसे समझते हैं, तो उस प्रोग्रामर के दिमाग पर सवाल होगा ... इस कोड के लेखक ने इसे क्यों लिखा है? और यदि आपके पास उस प्रश्न के लिए एक अच्छा जवाब नहीं है (उदाहरण के लिए, क्योंकि आप स्पष्ट रूप से ओवरलोडिंग को रोकना चाहते हैं , जैसे कि रेंज अनुकूलन बिंदुओं में), तो आपको सामान्य तंत्र का उपयोग करना चाहिए।

जहाँ उपयुक्त हो उपन्यासों के अपेक्षित समाधानों को प्राथमिकता दें। अपनी बात रखने की कम से कम जटिल विधि का उपयोग करें।


9
"सी के दिनों के बाद से" जिस तरह से मेरे दोस्त से पहले
लाइटनेस दौड़ ऑर्बिट में

4
@LightnessRaces: मेरा मुख्य बिंदु यह व्यक्त करना था कि C ++ का फ़ंक्शन सिंटैक्स C के बाद से आसपास है, इसलिए बहुत सारे लोग जानते हैं कि यह निरीक्षण से क्या है।
निकोल बोलस

2
पहले वाक्य को छोड़कर इस जवाब से सभी सहमत हैं। "यह सामान्य नहीं है" एक अस्पष्ट और अस्पष्ट कथन है। शायद आप इसका अर्थ "यह असामान्य और भ्रमित है" के अर्थ में है?
ईनपोकलम

1
@einpoklum: C ++ में कई चीजें हैं जिन्हें "असामान्य और भ्रामक" माना जा सकता है जो अभी भी उनके डोमेन के भीतर काफी "सामान्य" हैं (गहरे टेम्पलेट मेटाप्रोग्रामिंग देखें)। मुझे लगता है कि "सामान्य" इस मामले में पूरी तरह से वैध है; यह एक ऐसी चीज नहीं है जो ऐतिहासिक और आज दोनों तरह के C ++ प्रोग्रामिंग अनुभव के "मानदंडों" के भीतर है।
निकोल बोल्स

@ नाइकोलोलस: लेकिन उस अर्थ में, यह परिपत्र तर्क है: ओपी सोच रहा है कि क्या हमें एक दुर्लभ प्रथा को अपनाना चाहिए। दुर्लभ प्रथाएं "आदर्श" नहीं हैं, लगभग परिभाषा के अनुसार। लेकिन एन.एम.
einpoklum

53

मैं कुछ ऐसे कारणों के बारे में सोच सकता हूं, जिन्हें आप नियमित रूप से कार्यों के लिए ड्रॉप-इन प्रतिस्थापन के रूप में वैश्विक लंबोदा से बचना चाहते हैं:

  • नियमित कार्य अतिभारित हो सकते हैं; lambdas नहीं कर सकते (हालांकि, इसे अनुकरण करने की तकनीकें हैं)
  • इस तथ्य के बावजूद कि वे कार्य-समान हैं, यहां तक ​​कि इस तरह से एक गैर-कैप्चरिंग लैम्ब्डा भी मेमोरी पर कब्जा कर लेगा (आमतौर पर गैर-कैप्चरिंग के लिए 1 बाइट)।
    • जैसा कि टिप्पणियों में कहा गया है, आधुनिक संकलक इस भंडारण को इस -अगर नियम के तहत दूर कर देंगे

"मुझे स्टेटफुल फंक्शनलर्स (क्लासेस) को बदलने के लिए लैम्बडा का उपयोग क्यों नहीं करना चाहिए?"

  • कक्षाओं में केवल लंबोदा की तुलना में कम प्रतिबंध हैं और इसलिए पहली बात यह होनी चाहिए कि आप किस चीज के लिए पहुंचते हैं
    • (सार्वजनिक / निजी डेटा, ओवरलोडिंग, सहायक तरीके आदि)
  • यदि लंबोदर के पास राज्य है, तो यह वैश्विक होने के कारण सभी के लिए तर्क करना अधिक कठिन है।
    • हमें सबसे कम संभव दायरे में एक वर्ग का उदाहरण बनाना पसंद करना चाहिए
  • गैर-कैप्चरिंग लैम्ब्डा को फ़ंक्शन पॉइंटर में बदलना पहले से ही मुश्किल है, और लैम्बडा के लिए यह असंभव है जो इसके कैप्चर में कुछ भी निर्दिष्ट करता है।
    • कक्षाएं हमें फ़ंक्शन पॉइंटर्स बनाने के लिए एक सीधा रास्ता देती हैं, और वे यह भी बताती हैं कि कई प्रोग्रामर किसके साथ अधिक सहज हैं
  • किसी भी कब्जा के साथ लम्बदा डिफ़ॉल्ट रूप से निर्मित नहीं किया जा सकता है (C ++ 20 में। पहले किसी भी मामले में कोई डिफ़ॉल्ट निर्माता नहीं था)

लैंबडा के लिए "यह" सूचक भी है (यहां तक ​​कि एक गैर-कैप्चरिंग भी) जो लैंबडा बनाम फ़ंक्शन को कॉल करते समय एक अतिरिक्त पैरामीटर के परिणामस्वरूप होता है।
1201ProgramAlarm

@ 1201ProgramAlarm: यह एक अच्छी बात है; एक
लंबर के

3
फ्लिप-साइड पर, अगर इसे सीधे बुलाया जाने के बजाय कहीं पास किया जाता है, तो फ़ंक्शन के बजाय लंबोदर होने से इनलाइनिंग को बढ़ावा मिलता है। स्वाभाविक रूप से, कोई भी इसके लिए फ़ंक्शन-पॉइंटर पैक कर सकता std::integral_constantहै ...
डेडुप्लिकेटर

@Deduplicator: " फ़ंक्शन के बजाय लंबोदर होने " केवल स्पष्ट होने के लिए प्रेरित करता है , यह केवल तभी लागू होता है यदि "कहीं" एक टेम्पलेट है जो फ़ंक्शन को एक सूचक सूचक के बजाय एक मनमाना कॉल करने योग्य प्रकार के रूप में कॉल करता है।
निकोल बोलस

2
@AndyG आप इस प्रकार के नियम को भूल रहे हैं: ऐसे प्रोग्राम जो लंबोदर के आकार का अनुरोध नहीं करते हैं (क्योंकि ... क्यों?), और न ही इसके लिए एक संकेतक बनाएं, (और आम तौर पर नहीं) की आवश्यकता नहीं है इसके लिए जगह आवंटित करें।
कोनराड रुडोल्फ

9

पूछने के बाद, मैंने ऐसा न करने का एक कारण सोचा: चूंकि ये चर हैं, वे स्टेटिक इनिशियलाइज़ेशन ऑर्डर फासको ( https://isocpp.org/wiki/faq/ctors#static-init-order ) के लिए प्रवण हैं , जो कारण नीचे लाइन कीड़े।


आप उन्हें मेमना बना सकते हैं constexpr... असली मुद्दा यह है: बस एक फ़ंक्शन का उपयोग करें।
einpoklum

8

क्या "नियमित" वैश्विक कार्यों के बजाय हर जगह केवल लैम्ब्डा का उपयोग करने का कोई कारण नहीं है?

जटिलता के एक निश्चित स्तर की समस्या के लिए कम से कम उसी जटिलता के समाधान की आवश्यकता होती है। लेकिन अगर एक ही समस्या के लिए कम जटिल समाधान है, तो वास्तव में अधिक जटिल का उपयोग करने का कोई औचित्य नहीं है। जटिलता की आवश्यकता क्यों है?

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


6

लैम्ब्डा अनाम फ़ंक्शन हैं

यदि आप नामांकित लैम्बडा का उपयोग कर रहे हैं, तो इसका मतलब है कि आप मूल रूप से नामांकित फ़ंक्शन का उपयोग कर रहे हैं। इस ऑक्सीमोरोन से बचने के लिए, आप एक फ़ंक्शन का उपयोग कर सकते हैं।


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

@KonradRudolph: यह केवल शब्दावली नहीं है, इसीलिए उन्हें पहली जगह में बनाया गया था। कम से कम ऐतिहासिक रूप से, लंबोदर अनाम कार्य हैं, और इसीलिए यह उन्हें नाम देने के लिए भ्रमित है, खासकर जब कार्यों के बजाय उम्मीद की जाएगी।
एरिक डुमिनील

1
नाह। लम्बदा को नियमित रूप से नामांकित किया जाता है (बस आमतौर पर स्थानीय रूप से), इस बारे में कुछ भी भ्रमित नहीं है।
कोनराड रूडोल्फ

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

5

अगर लम्बडा के रूप में इसे छोड़ने का कोई कारण नहीं है? क्या "नियमित" वैश्विक कार्यों के बजाय हर जगह केवल लैम्ब्डा का उपयोग करने का कोई कारण नहीं है?

हमने वैश्विक फ़नकार के बजाय फ़ंक्शंस का उपयोग किया, इसलिए यह सुसंगतता और कम से कम विस्मय के सिद्धांत को तोड़ता है ।

मुख्य अंतर हैं:

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