गो में नेस्टेड फ़ंक्शन घोषणाओं की अनुमति नहीं देने से क्या समस्याएं हैं जो कम हो जाती हैं?


87

लैम्ब्डा उम्मीद के मुताबिक काम करते हैं:

func main() {
    inc := func(x int) int { return x+1; }
}

हालाँकि, एक घोषणा के अंदर निम्नलिखित घोषणा की अनुमति नहीं है:

func main() {
    func inc(x int) int { return x+1; }
}

किस कारण से नेस्टेड फ़ंक्शन की अनुमति नहीं है?


हम्म मैं नहीं जानता कि क्या आप ऐसा करने का मतलब है func main() { func (x int) int { return x+1; }(3) }
ymg

@YasirG। लेकिन यह एक भेड़ का बच्चा भी है, है ना? मुझे आपकी टिप्पणी नहीं मिली ...
corazza

सिंटैक्स अनुमति में दूसरी कार्यक्षमता को क्या कार्यक्षमता सक्षम करेगी, जो पहले मामले से समर्थित नहीं है?
Not_a_Golfer

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

@Not_a_Golfer: एक संभावना यह है कि जावास्क्रिप्ट जिस तरह से लागू होता है, उसे लागू करने के लिए अनिवार्य रूप से एक फ़ंक्शन को एक चर में असाइन करना फ़ंक्शन को घोषित करने की तुलना में बहुत अलग है क्योंकि नियंत्रण का प्रवाह ऐसे चर को प्रभावित करता है, जबकि जावास्क्रिप्ट में कार्य प्रभावित नहीं होते हैं। इसका मतलब है कि आप inc()वास्तविक घोषणा से पहले दूसरे उदाहरण में कॉल कर सकते हैं । परंतु! मैं कारणों की तलाश कर रहा हूं, मुझे गो के बारे में ज्यादा जानकारी नहीं है लेकिन मैं सीखना चाहूंगा कि इस नियम के पीछे तर्क क्या था।
corazza

जवाबों:


54

मुझे लगता है कि इस स्पष्ट सुविधा की अनुमति नहीं देने के 3 कारण हैं

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

हालांकि वे सिर्फ मेरी राय हैं - मैंने भाषा डिजाइनरों से आधिकारिक घोषणा नहीं देखी है।


2
पास्कल (कम से कम यह डेल्फी अवतार है) उन्हें सही और सरल मिला: नेस्टेड फ़ंक्शन नियमित रूप से व्यवहार करते हैं, लेकिन उनके एन्कोडिंग फ़ंक्शन के दायरे में चर तक पहुंच भी है। मुझे नहीं लगता कि इन पर अमल करना मुश्किल है। दूसरी ओर, बहुत सारे डेल्फी कोड लिखे होने के कारण मुझे यकीन नहीं है कि मुझे बुरी तरह से नेस्टेड कार्यों की आवश्यकता है: कभी-कभी वे निफ्टी महसूस करते हैं, लेकिन वे एन्क्लोजिंग फ़ंक्शन को उड़ा देते हैं, जिससे यह शायद ही पठनीय हो। अपने माता-पिता के तर्कों को एक्सेस करने से प्रोग्राम को पढ़ने में मुश्किल हो सकती है क्योंकि इन चर को आसानी से एक्सेस किया जाता है (औपचारिक मापदंडों के रूप में पारित नहीं किया जाता है)।
कोस्टिक्स

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

47

निश्चित ही वे हैं। आपको बस उन्हें एक चर में निर्दिष्ट करना है:

func main() {
    inc := func(x int) int { return x+1; }
}

5
ध्यान देने योग्य है, आप ऐसे कार्यों (inc) को पुनरावर्ती नहीं कह सकते।
मोहसिन काले

1
इसे पुनरावर्ती रूप से कॉल करने के लिए, आपको आगे की घोषणा करने की आवश्यकता हैvar inc func(int) int
इज़ाना

28

अक्सर पूछे जाने वाले प्रश्न (एफएक्यू)

Go में फीचर X क्यों नहीं है?

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

यदि यह आपको परेशान करता है कि Go में सुविधा X गायब है, तो कृपया हमें क्षमा करें और उन सुविधाओं की जांच करें जो Go के पास हैं। आप पा सकते हैं कि वे एक्स की कमी के लिए दिलचस्प तरीकों से क्षतिपूर्ति करते हैं।

नेस्टेड फ़ंक्शंस को जोड़ने की जटिलता और खर्च का क्या औचित्य होगा? क्या आप ऐसा करना चाहते हैं कि आप नेस्टेड कार्यों के बिना नहीं कर सकते हैं? Et cetera।


19
निष्पक्ष होने के लिए, मुझे नहीं लगता कि किसी ने किसी विशेष जटिलता का प्रदर्शन किया है जो कि नेस्टेड कार्यों को अनुमति देगा। इसके अलावा, जब मैं उद्धृत दर्शन से सहमत हूं, तो मुझे यकीन नहीं है कि यह नेस्टेड फ़ंक्शन को "सुविधा" के रूप में संदर्भित करना उचित है, क्योंकि एक सुविधा के रूप में उनके चूक का जिक्र है। क्या आप किसी भी जटिलताओं के बारे में जानते हैं जो नेस्टेड फ़ंक्शन की अनुमति देगा? मैं मान रहा हूँ कि वे सिर्फ लैम्ब्डा के लिए सिंटैक्टिक शुगर होंगे (मैं किसी अन्य उचित व्यवहार के बारे में नहीं सोच सकता)।
joshlf

चूंकि गो को संकलित किया गया है, यह AFAIK करने का एकमात्र तरीका है, लैम्ब्डा को परिभाषित करने के लिए एक और वाक्यविन्यास बनाएगा। और मैं वास्तव में उस के लिए एक उपयोग मामला नहीं देख रहा हूँ। आपके पास वास्तविक समय में बनाए गए स्थिर फ़ंक्शन के भीतर एक स्थिर फ़ंक्शन नहीं हो सकता है - क्या होगा अगर हम फ़ंक्शन को परिभाषित करने वाले विशिष्ट कोड पथ में प्रवेश नहीं करते हैं?
Not_a_Golfer

बस लैम्ब्डा इंटरफ़ेस {} में पास करें और टाइप करें। उदाहरण के लिए। f_lambda: = lambda (func () rval {}) या जो भी प्रोटोटाइप होगा। फंक डिक्लेयर सिंटैक्स इसका समर्थन नहीं करता है लेकिन भाषा पूरी तरह से करती है।
बैडज़ेन


8

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

उदाहरण:

func outerFunction(iterations int, s1, s2 string) int {
    someState := 0
    innerFunction := func(param string) int {
        // Could have another nested function here!
        totalLength := 0
        // Note that the iterations parameter is available
        // in the inner function (closure)
        for i := 0; i < iterations; i++) {
            totalLength += len(param)
        }
        return totalLength
    }
    // Now we can call innerFunction() freely
    someState = innerFunction(s1)
    someState += innerFunction(s2)
    return someState
}
myVar := outerFunction(100, "blah", "meh")

आंतरिक कार्य अक्सर स्थानीय गोरोइन के लिए उपयोगी होते हैं:

func outerFunction(...) {
    innerFunction := func(...) {
        ...
    }
    go innerFunction(...)
}

सादे समारोह से कुछ पहलुओं में अंतर बंद हो जाता है। उदाहरण के लिए आप पुनरावृत्ति को बंद नहीं कह सकते।
माइकल ज़ैबेल्स्की

7
@ माइकलहैबेल्स्की: यदि आप इसे परिभाषित करने से पहले घोषित करते हैं, तो आप इसे पुनरावर्ती कह सकते हैं।
पी डैडी

1

आपको बस ()अंत में जोड़कर तुरंत कॉल करना होगा ।

func main() {
    func inc(x int) int { return x+1; }()
}

संपादित करें: फ़ंक्शन का नाम नहीं हो सकता ... इसलिए यह अभी एक लंबोदर फ़ंक है जिसे तुरंत कहा जाता है:

func main() {
    func(x int) int { return x+1; }()
}

1
उह जो एक फंक्शन डेफिनिशन की अपेक्षा के अनुरूप नहीं है
corazza

1
@corazza आह, जब मैंने प्रश्न पढ़ा तो मैंने "घोषणा" शब्द को याद किया। मेरी गलती।
निक

1
@corazza इसके अलावा, मैंने सिंटैक्स को भी खराब कर दिया है। फ़ंक्शन नाम को निकालने की आवश्यकता है। तो, यह मूल रूप से एक लंबो फ़ंक्शन है जिसे तुरंत कहा जाता है।
निक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.