लैम्बडा मैक्रो कैसे लैम्बडा बनाता है?


20

मुझे GitHub पर कोड का यह टुकड़ा मिला लेकिन यह काफी समझ में नहीं आया:

#define lambda(ret_type, _body) ({ ret_type _ _body _; })

फिर:

int (*max)(int, int) = lambda(int,
                             (int x, int y) {
                                 return x > y ? x : y;
                             });

int max_value = max(1, 2);
// max_value is 2

अंडरस्कोर अंदर क्या कर रहे हैं #defineऔर यह एक फ़ंक्शन पॉइंटर कैसे लौटाता है?


7
क्या आपने केवल मैक्रो का विस्तार करने की कोशिश की है (उदाहरण के साथ gcc -E) यह देखने के लिए कि यह क्या करता है?
बेकार

5
कृपया विस्तार से देखें godbolt.org/z/C5TLWj परिणाम को समझना आसान नहीं है
यूजीन श।

2
मुझे लगता है कि आप उस जगह के आसपास टिप्पणियों के आधार पर जानते हैं जहां आपको यह कोड मिला है, लेकिन यह नेस्टेड फ़ंक्शन के लिए जीसीसी एक्सटेंशन पर निर्भर करता है।
थॉमस जैगर

4
@EugeneSh। यह GCC के नेस्टेड फ़ंक्शन का उपयोग करके एक फ़ंक्शन पॉइंटर को इनिशियलाइज़ कर रहा है। मूल कोड यहाँ से है । यह प्रोजेक्ट आज हैकर न्यूज़ पर साझा किया गया।
थॉमस जैगर

4
@EugeneSh। यह दो GCC एक्सटेंशन का संयोजन है: नेस्टेड फ़ंक्शंस, और एक्सप्रेशन में यौगिक कथनों । नेस्टेड फ़ंक्शन कंपाउंड स्टेटमेंट के अंदर दिखाई देता है।
इंटरजेन

जवाबों:


10

इस मैक्रो का उपयोग करते हुए,

int (*max)(int, int) = lambda(int,
                             (int x, int y) {
                                 return x > y ? x : y;
                             });

इसका विस्तार:

int (*max)(int, int) = ({
    int _ (int x, int y) { return x > y ? x : y; }
    _;
});

घुंघराले ब्रेसिज़ में, यह एक फ़ंक्शन बनाने के लिए जीसीसी के नेस्टेड फ़ंक्शंस का उपयोग करता है जो वांछित ऑपरेशन करता है। भीतर के दायरे में, इसका नाम है _

फिर, जैसा कि अंतरजाल द्वारा उल्लेख किया गया है, जीसीसी के स्टेटमेंट एक्सप्रेशंस का उपयोग किया जाता है। प्रभावी रूप से, फ़ंक्शन _पॉइंटर को सौंपा गया है max

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

int val1 = 4;
int val2 = -30;

int perform_operation(int (*op)(int, int)) {
    int new_val = op(val1, val2);
    val1 = val2;
    val2 = new_val;
    return new_val;
}

int enclosing_function (void) {
    // Create max "lambda"
    int (*max)(int, int);
    {
        // Curly braces limit the scope of _
        int _ (int x, int y) { return x > y ? x : y; }
        max = _;
    }

    return perform_operation(max);
}

इस कोड उदाहरण में तीन तरीकों की तुलना की जा सकती है ।


मैक्रो कुछ भी नहीं करता है क्योंकि यह gcc में संकलित नहीं करेगा
P__J__


@P__J__ मैंने अपने उत्तर के अंत में एक उदाहरण जोड़ा है जो इस मैक्रो का उपयोग करता है।
थॉमस जैगर

आप इसके max(4, -30);बजाय क्यों नहीं कर सकते apply_binary_op(max, 4, -30);?
एसएस ऐनी

1
"अभिव्यक्तियों में मिश्रित विवरण" को "कथन अभिव्यक्ति" कहा जाता है। वे मान जिनका कोई मान हो (जैसे) किसी चीज़ को सौंपा जा सकता है।
पीटर कॉर्डेस

7

इसे एक स्टेटमेंट एक्सप्रेशन कहा जाता है और एक "लैम्ब्डा" (या नेस्टेड फंक्शन ) बनाता है और इसके लिए एक पॉइंटर देता है। यह जीएनयू सी-विशिष्ट है।

मैक्रो का विस्तार:

int (*max)(int, int) = ({ int _ (int x, int y) { return x > y ? x : y; } _; })

_अंत में एक की तरह है return

अंडरस्कोर वास्तव में उस फ़ंक्शन का नाम है जो बनाया गया है और "लौटाया गया" है। इसका उपयोग किया जाता है क्योंकि यह एक असामान्य रूप से उपयोग किया जाने वाला पहचानकर्ता है (अच्छे कारण के लिए; _यह संभवतः संभवतः सबसे कम वर्णनात्मक पहचानकर्ता है)।

जिस कारण से स्टेटमेंट एक्सप्रेशन का उपयोग किया जाता है _, उसे स्टेटमेंट एक्सप्रेशन के दायरे से बाहर होने के बाद परिभाषित नहीं किया जाएगा।

तो, मैक्रो के माध्यम से जा रहा है:

#define lambda(ret_type, _body) ({ ret_type _ _body _; })

ret_type"लैम्ब्डा" का रिटर्न प्रकार है। _इसके अंदर उपयोग किए जाने वाले फ़ंक्शन का नाम है क्योंकि यह एक असामान्य पहचानकर्ता नाम है। _bodyफ़ंक्शन के तर्क और निकाय शामिल हैं। अनुगामी _" लंबा " लौटाता है।

यह कोड लेट्स नष्ट सी (जो एक उपयुक्त नाम है) में पाया जाता है। आपको इसका उपयोग नहीं करना चाहिए। यह आपके कोड को केवल उन कंपाइलरों पर काम करेगा जो GNU C एक्सटेंशन का समर्थन करते हैं। इसके बजाय, बस एक फ़ंक्शन या मैक्रो लिखें।

यदि आप इस तरह के निर्माण का उपयोग करते हैं या अधिक सुविधाएँ चाहते हैं, तो मैं सुझाव देता हूं कि C ++ का उपयोग करें। C ++ से आप ऐसा ही कुछ कर सकते हैं और पोर्टेबल कोड रख सकते हैं ।

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