गैर-कार्यात्मक सेटिंग में क्लोज़र को लागू करने में समस्याएं


18

प्रोग्रामिंग भाषाओं में, क्लोजर एक लोकप्रिय और अक्सर वांछित विशेषता है। विकिपीडिया कहता है (जोर मेरा):

कंप्यूटर विज्ञान में, एक क्लोजर (...) एक फ़ंक्शन है जो उस फ़ंक्शन के गैर-स्थानीय चर के लिए संदर्भित वातावरण के साथ है। एक क्लोजर एक फ़ंक्शन को इसके तत्काल शाब्दिक दायरे के बाहर चर का उपयोग करने की अनुमति देता है।

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

व्यवहार में, अवधारणा का विचलन प्रतीत होता है, हालांकि, कम से कम कार्यात्मक प्रोग्रामिंग के बाहर। अलग-अलग भाषाएं अलग-अलग शब्दार्थों को लागू करती हैं, यहां तक ​​कि उन पर शब्दकोषों के युद्ध भी प्रतीत होते हैं। कई प्रोग्रामर्स को यह पता नहीं लगता है कि क्लोजर क्या हैं, उन्हें अनाम कार्यों की तुलना में थोड़ा अधिक देखना।

इसके अलावा, बंद लागू करते समय बड़ी बाधाएं मौजूद हैं। सबसे उल्लेखनीय, जावा 7 उन्हें शामिल करने वाला था लेकिन इस सुविधा को भविष्य के रिलीज पर वापस धकेल दिया गया था।

क्यों एहसास करने के लिए (समझने के लिए) और क्यों बंद कर रहे हैं? यह बहुत व्यापक है और एक प्रश्न अस्पष्ट है, इसलिए मुझे इन परस्पर प्रश्नों के साथ अधिक ध्यान केंद्रित करने दें:

  • क्या सामान्य अर्थ औपचारिकताओं (छोटे-कदम, बड़े-कदम, ...) में अभिव्यक्त होने वाली समस्याएं हैं?
  • क्या मौजूदा प्रकार के सिस्टम क्लोजर के अनुकूल नहीं हैं और इन्हें आसानी से बढ़ाया नहीं जा सकता है?
  • क्या यह एक पारंपरिक, स्टैक-आधारित प्रक्रिया अनुवाद के अनुरूप बंद करने के लिए समस्याग्रस्त है?

ध्यान दें कि प्रश्न सामान्य रूप से ज्यादातर प्रक्रियात्मक, वस्तु-उन्मुख और स्क्रिप्टिंग भाषाओं से संबंधित है। जहाँ तक मुझे पता है, कार्यात्मक भाषाओं में कोई समस्या नहीं है।


अच्छा प्रश्न। स्कैला में क्लोज़र लागू किया गया है, और मार्टिन ओडस्की ने जावा 1.5 संकलक लिखा है, इसलिए यह स्पष्ट नहीं है कि वे जावा 7. सी # में क्यों नहीं हैं। (मैं बाद में एक बेहतर जवाब लिखने की कोशिश करूँगा।)
डेव क्लार्क

4
लिस्प और एमएल जैसी कार्यात्मक भाषाओं को बंद करना ठीक है, इसलिए उनके लिए समस्याग्रस्त होने का आंतरिक अर्थ नहीं हो सकता है।
गिल्स एसओ- बुराई को रोकना '

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

1
Pdfs.semanticscholar.org/73a2/… पर एक नज़र डालें - लुआ के लेखकों ने इसे बहुत ही चतुर तरीके से बनाया और क्लोजर को लागू करने की सामान्य समस्याओं पर चर्चा की
Bulat

जवाबों:


10

क्या मैं आपको फ़नकार समस्या विकिपीडिया पृष्ठ पर निर्देशित कर सकता हूँ ? कम से कम यह है कि कंपाइलर लोगों ने क्लोजर कार्यान्वयन समस्या का संदर्भ दिया।

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

हालांकि यह परिभाषा समझ में आती है, यह पारंपरिक रनटाइम-स्टैक आधारित भाषा में प्रथम श्रेणी के कार्यों को लागू करने की समस्या का वर्णन करने में मदद नहीं करता है। जब कार्यान्वयन के मुद्दों की बात आती है, तो प्रथम श्रेणी के कार्यों को मोटे तौर पर दो वर्गों में विभाजित किया जा सकता है:

  • फ़ंक्शन में स्थानीय चर का उपयोग फ़ंक्शन रिटर्न के बाद कभी नहीं किया जाता है।
  • फंक्शन रिटर्न के बाद स्थानीय वेरिएबल्स का उपयोग किया जा सकता है।

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

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


जावा के विशेष उदाहरण के रूप में, अगर मुझे सही से याद है, तो मुख्य मुद्दा वास्तव में क्लोजर को लागू करने में सक्षम नहीं था, लेकिन उन्हें इस तरह से भाषा से कैसे परिचित कराया जाए जो मौजूदा सुविधाओं (जैसे गुमनाम आंतरिक वर्गों) के साथ बेमानी नहीं था और वह मौजूदा सुविधाओं से नहीं टकराया था (जैसे कि जाँच किए गए अपवाद - एक समस्या जो हल करने के लिए सामान्य ज्ञान एल नहीं है और जो ज्यादातर लोग पहले नहीं सोचते हैं)।

मैं भी इस तरह के क्या जैसे कि "जादुई" चर के साथ क्या करने का निर्णय लेने के रूप में अन्य चीजें हैं जो प्रथम श्रेणी कार्यों कम लागू करने के लिए तुच्छ बनाने के लिए, के बारे में सोच सकते हैं इस , स्वयं या सुपर और कैसे इस तरह के रूप में मौजूदा नियंत्रण प्रवाह ऑपरेटरों, के साथ बातचीत करने को तोड़ने और वापसी (क्या हम गैर-स्थानीय रिटर्न के लिए अनुमति देना चाहते हैं या नहीं?)। लेकिन अंत में, प्रथम श्रेणी के कार्यों की हालिया लोकप्रियता यह संकेत देती है कि ऐसी भाषाएं जो उनके पास नहीं हैं वे ज्यादातर ऐतिहासिक कारणों से या कुछ महत्वपूर्ण डिजाइन निर्णय जल्दी शुरू होने के कारण ऐसा करती हैं।


1
क्या आप ऐसी किसी भी भाषा के बारे में जानते हैं जो ऊपर और नीचे के मामलों को अलग करती है? .NET भाषाओं में, एक सामान्य विधि, जो केवल-डाउन फ़ंक्शन प्राप्त करने की अपेक्षा करती है, एक प्रतिनिधि के साथ-साथ सामान्य प्रकार की संरचना प्राप्त कर सकती है जो इस तरह की संरचना को byref (C #, एक " refपैरामीटर") के रूप में प्राप्त करेगी । यदि कॉलर ने संरचना में ब्याज के सभी चर को अलग कर दिया, तो प्रतिनिधि को पूरी तरह से स्थिर हो सकता है, एक ढेर आवंटन की आवश्यकता से बचता है। कंपाइलर ऐसे निर्माणों के लिए कोई अच्छा वाक्यविन्यास सहायता प्रदान नहीं करते हैं, लेकिन फ्रेमवर्क उनका समर्थन कर सकता है।
सुपरकैट

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

5

हम यह देख सकते हैं कि C # में क्लोजर कैसे लागू किया जाता है। परिवर्तनों का पैमाना C # संकलक करता है यह स्पष्ट करता है कि क्लोजर को लागू करने का उनका तरीका बहुत काम है। क्लोजर को लागू करने के आसान तरीके हो सकते हैं, लेकिन मुझे लगता है कि सी # कंपाइलर टीम को इसकी जानकारी होगी।

निम्नलिखित छद्म सी # पर विचार करें (मैं सी # विशिष्ट सामान का एक सा काट दिया):

int x = 1;
function f = function() { x++; };
for (int i = 1; i < 10; i++) {
    f();
}
print x; // Should print 9

संकलक इसे कुछ इस तरह से रूपांतरित करता है:

class FunctionStuff {
   int x;
   void theFunction() {
       x++;
   }
}

FunctionStuff theClosureObject = new FunctionStuff();
theClosureObject.x = 1;
for (int i = 1; i < 10; i++) {
    theClosureObject.theFunction();
}
print theClosureObject.x; // Should print 9

(वास्तव में, चर f अभी भी बनाया जाएगा, जहाँ f एक 'डेलीगेट' (= फंक्शन पॉइंटर) है, लेकिन यह डेलीगेट अभी भी theClosureObject ऑब्जेक्ट के साथ जुड़ा हुआ है - मैंने यह हिस्सा उन लोगों के लिए स्पष्टता के लिए छोड़ दिया है जो परिचित हैं सी # के साथ)

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


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

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

@ राफेल: आप अंदर की बंदियों के बारे में कैसा महसूस करते हैं? रुको, मुझे इसमें जोड़ें।
एलेक्स दस ब्रिंक

5

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


संदर्भ के लिए धन्यवाद! यह प्रकाश पढ़ने के लिए बनाने के लिए नहीं लगता है, लेकिन यह एक शब्दार्थक पेपर से उम्मीद की जा सकती है।
राफेल

1
@ राफेल: शायद आसपास सरल हैं। मैं कुछ खोजने और आपके पास वापस आने की कोशिश करूँगा। किसी भी मामले में, चित्र 8 में आपके द्वारा खोजे जाने वाले शब्दार्थ हैं।
डेव क्लार्क

हो सकता है कि आप एक मोटे तौर पर अवलोकन सम्मान दे सकें। आपके उत्तर में केंद्रीय विचार?
राफेल

2
@Raphael। शायद मैं आपको अपने व्याख्यान नोट्स के लिए संदर्भित कर सकता हूं जो मैं प्रोग्रामिंग भाषाओं के पाठ्यक्रम के लिए उपयोग करता हूं, जो आपको त्वरित परिचय देता है। कृपया हैंडआउट 8 और 9 देखें
उदय रेड्डी

1
वह लिंक या तो मृत प्रतीत होता है या अदृश्य प्रमाणीकरण के पीछे। ( cs.cmu.edu/afs/cs/user/rwh/public/www/home/papers/gcpoly/tr.pdf )। मुझे 403 मना है।
बेन फ्लेचर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.