क्या सभी कार्यात्मक भाषाएं कचरा संग्रहण का उपयोग करती हैं?


32

क्या एक कार्यात्मक भाषा है जो स्केम शब्दार्थ का उपयोग करने की अनुमति देती है - गुंजाइश के अंत में स्वचालित निर्धारक विनाश?


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

मैं सवाल के संदर्भ में दिलचस्पी रखता हूं, एक व्यक्ति को ओथर के साथ क्या करना है?
मटनज

1
कचरा संग्रह के बिना एक कार्यात्मक भाषा में, मैं यह नहीं देखता कि अपरिवर्तनीय डेटा संरचनाओं का संरचनात्मक साझाकरण कैसे संभव है। ऐसी भाषा बनाना संभव हो सकता है, लेकिन यह वह नहीं है जिसका मैं उपयोग करूंगा।
dan_waterworth

जंग में बहुत सारी विशेषताएं होती हैं जिन्हें आमतौर पर 'कार्यात्मक' के रूप में पहचाना जाता है (कम से कम, वे आमतौर पर कार्यात्मक सुविधाओं के रूप में गैर-फंक लैंग्स में चाहते हैं)। मैं उत्सुक हूँ कि यह क्या याद आ रही है। डिफ़ॉल्ट रूप से, क्लोजर, फंक पासिंग, प्रिंटेड ओवरलोडिंग, ADTs (अभी तक कोई GADTs नहीं), पैटर्न मिलान, सभी बिना GC के। और क्या?
नोइन

जवाबों:


10

ऐसा नहीं है कि मुझे पता है, हालांकि मैं कोई कार्यात्मक प्रोग्रामिंग विशेषज्ञ नहीं हूं।

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

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

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

कुछ बिंदु पर (साहचर्य रचना की श्रृंखला के दाईं ओर) आपको घोंसले को समाप्त करने के लिए किसी तरह के टर्मिनेटर की आवश्यकता है - बीच में छेद को भरने के लिए कुछ। एक टर्मिनेटर की आवश्यकता है, जिसका अर्थ है कि शायद घोंसला बनाने वाला संचालक संन्यासी नहीं है, हालांकि फिर से, मुझे पूरी तरह से यकीन नहीं है क्योंकि मैंने विवरण के माध्यम से काम नहीं किया है। जैसा कि सभी टर्मिनेटर लागू करता है एक घोंसले के शिकार कार्रवाई को प्रभावी रूप से एक सामान्य सामान्य मानदिक कार्रवाई में परिवर्तित करता है, शायद नहीं - यह जरूरी नहीं कि घोंसले के शिकार ऑपरेटर को प्रभावित करें।

इनमें से कई विशेष क्रियाओं में एक अशक्त "एंड-टैग" कदम होगा, और कुछ सरल मोनडिक कार्रवाई के साथ "शुरुआती-टैग" चरण की समानता होगी। लेकिन कुछ परिवर्तनशील घोषणाओं का प्रतिनिधित्व करेंगे। ये शुरुआती टैग के साथ कंस्ट्रक्टर का प्रतिनिधित्व करते हैं, और अंत-टैग के साथ विध्वंसक। तो आपको कुछ ऐसा मिलता है ...

act = terminate ((def-var "hello" ) >>>= \h ->
                 (def-var " world") >>>= \w ->
                 (use-val ((get h) ++ (get w)))
                )

निम्नलिखित निष्पादन के आदेश के साथ एक राक्षसी रचना में अनुवाद, प्रत्येक टैग (तत्व नहीं) एक सामान्य मोनडिक क्रिया बन जाती है ...

<def-var val="hello">  --  construction
  <def-var val=" world>  --  construction
    <use-val ...>
      <terminator/>
    </use-val>  --  do nothing
  </def-val>  --  destruction
</def-val>  --  destruction

इस तरह के नियम C ++ शैली RAII को लागू करने की अनुमति दे सकते हैं। IORef जैसे संदर्भ उनके दायरे से बच नहीं सकते हैं, समान कारणों से सामान्य IORefs मठ से बच नहीं सकते हैं - साहचर्य रचना के नियम संदर्भ से बचने का कोई रास्ता नहीं प्रदान करते हैं।

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

इसलिए, निर्माण उदा एक फ़ाइल खोल सकता है जो विनाश को बंद कर देता है। निर्माण एक सॉकेट खोल सकता है जो विनाश को बंद कर देता है। मूल रूप से, C ++ में, चर संसाधन प्रबंधक बन जाते हैं। लेकिन C ++ के विपरीत, ऐसे ढेर-आवंटित ऑब्जेक्ट नहीं हैं जो स्वचालित रूप से नष्ट नहीं किए जा सकते हैं।

यद्यपि यह संरचना RAII का समर्थन करती है, फिर भी आपको कचरा कलेक्टर की आवश्यकता है। हालाँकि, एक नेस्टिंग क्रिया, मेमोरी को आवंटित और मुक्त कर सकती है, लेकिन इसे एक संसाधन के रूप में मानते हुए, स्मृति और उस जगह के भीतर (संभवतः साझा) कार्यात्मक मूल्यों के सभी संदर्भ हैं। यह देखते हुए कि मेमोरी को केवल ढेर पर आवंटित किया जा सकता है, ढेर मुक्त की आवश्यकता से बचते हुए, वास्तविक महत्व (यदि कोई है) अन्य प्रकार के संसाधन प्रबंधन के लिए है।

तो यह क्या प्राप्त होता है RAII- शैली संसाधन प्रबंधन को स्मृति प्रबंधन से अलग करने के लिए, कम से कम उस स्थिति में जहां RAII सरल डस्टिंग स्कोप पर आधारित है। आपको स्मृति प्रबंधन के लिए अभी भी एक कचरा कलेक्टर की आवश्यकता है, लेकिन आप अन्य संसाधनों के सुरक्षित और समय पर स्वचालित निर्धारक सफाई प्राप्त करते हैं।


मैं यह देखने में विफल हूं कि सभी कार्यात्मक भाषाओं में जीसी क्यों आवश्यक है। यदि आपके पास जगह में C ++ शैली RAII ढांचा है, तो संकलक उस तंत्र का भी उपयोग कर सकता है। साझा मूल्य RAII चौखटे के लिए कोई समस्या नहीं है (देखें C ++ 's shared_ptr<>), आप अभी भी नियतात्मक विनाश रखते हैं। RAII के लिए एक चीज़ जो मुश्किल है, वह है चक्रीय संदर्भ; RAII साफ़ सफाई से काम करता है यदि स्वामित्व ग्राफ एक प्रत्यक्ष Acyclic ग्राफ़ है।
MSalters

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

@ आगामी स्टॉर्म - C ++ में लैम्ब्डा (C ++ 11 के रूप में) है, लेकिन कोई मानक कचरा संग्राहक नहीं है। लैम्ब्डा अपने पर्यावरण को एक बंद में भी ले जाते हैं - और उस वातावरण में तत्वों को संदर्भ द्वारा पारित किया जा सकता है, साथ ही संकेत के मूल्य द्वारा पारित होने की संभावना हो सकती है। लेकिन जैसा कि मैंने अपने दूसरे पैराग्राफ में लिखा है, C ++ पॉइंटर्स को झूलने की संभावना देता है - यह प्रोग्रामर (संकलक या रनटाइम वातावरण के बजाय) की जिम्मेदारी है कि यह सुनिश्चित करें कि ऐसा कभी नहीं होता है।
स्टीव ३१

@MSalters - यह सुनिश्चित करने में लागतें शामिल हैं कि कोई भी संदर्भ चक्र कभी भी नहीं बनाया जा सकता है। इसलिए उस प्रतिबंध के लिए भाषा को जिम्मेदार बनाना कम से कम गैर-तुच्छ है। पॉइंटर को असाइन करना संभवतः एक गैर-स्थिर-समय ऑपरेशन बन जाता है। हालांकि यह अभी भी कुछ मामलों में सबसे अच्छा विकल्प हो सकता है। कचरा संग्रह उस मुद्दे से बचता है, अलग-अलग लागतों के साथ। प्रोग्रामर को जिम्मेदार बनाना एक और है। इस बात का कोई मजबूत कारण नहीं है कि झूलने वाले पॉइंट्स को अनिवार्य नहीं बल्कि कार्यात्मक भाषाओं में ठीक होना चाहिए, लेकिन मैं अभी भी पॉइंटर-झूलने-हास्केल लिखने की सलाह नहीं देता हूं।
स्टीव ३१

मेरा तर्क है कि मैनुअल मेमोरी प्रबंधन का मतलब है कि आपके पास C ++ 11 क्लोजर का उपयोग करने की समान स्वतंत्रता नहीं है क्योंकि आप लिस्प या हास्केल क्लोजर करते हैं। (मैं वास्तव में इस ट्रेडऑफ़ के विवरण को समझने में काफी दिलचस्पी रखता हूं, क्योंकि मैं एक कार्यात्मक सिस्टम प्रोग्रामिंग भाषा लिखना चाहूंगा ...)
आने वाली

3

यदि आप C ++ को एक कार्यात्मक भाषा मानते हैं (इसमें लैम्ब्डा है), तो यह एक भाषा का एक उदाहरण है जो कचरा संग्रह का उपयोग नहीं करता है।


8
क्या होगा यदि आप C ++ को एक कार्यात्मक भाषा नहीं मानते हैं (IMHO यह नहीं है, हालांकि आप इसके साथ एक कार्यात्मक कार्यक्रम लिख सकते हैं, आप इसके साथ कुछ बेहद गैर-फ़्यूचेंशनल (कामकाजी ....) प्रोग्राम भी लिख सकते हैं)
मटनज़

@mattnz तब मुझे लगता है कि उत्तर लागू नहीं होता है। मुझे यकीन नहीं है कि अन्य भाषाओं में क्या होता है (उदाहरण के लिए हैसेल)
Bћови sure

9
C ++ को कार्यात्मक कहना यह कहने जैसा है कि पर्ल ऑब्जेक्ट-ओरिएंटेड है ...
डायनामिक

कम से कम c ++ कंपाइलर साइड इफेक्ट्स की जांच कर सकते हैं। (
कांस्टेबल के

@ tp1 - (1) मुझे आशा है कि यह इस बात को पुनः प्राप्त करने वाला नहीं है कि किसकी भाषा सबसे अच्छी है, और (2) यह वास्तव में सही नहीं है। सबसे पहले, वास्तव में महत्वपूर्ण प्रभाव ज्यादातर I / O हैं। दूसरा, यहां तक ​​कि परस्पर स्मृति पर प्रभाव के लिए, कास्ट उन्हें ब्लॉक नहीं करता है। यहां तक ​​कि अगर आप मानते हैं कि टाइपसिस्टम को हटाने की कोई संभावना नहीं है (आमतौर पर सी ++ में उचित है), तो तार्किक स्थिरता और "म्यूटेबल" सी ++ कीवर्ड का मुद्दा है। मूल रूप से, आप कब्ज के बावजूद म्यूटेशन कर सकते हैं। आपसे यह सुनिश्चित करने की अपेक्षा की जाती है कि परिणाम अभी भी "तार्किक रूप से" समान हो, लेकिन जरूरी नहीं कि वही प्रतिवेदन भी हो।
स्टीव 314

2

मेरा कहना है कि सवाल थोड़ा बीमार है, क्योंकि यह मानता है कि "कार्यात्मक भाषाओं" का एक मानक संग्रह है। लगभग हर प्रोग्रामिंग भाषा कार्यात्मक प्रोग्रामिंग की कुछ मात्रा का समर्थन करती है। और, लगभग हर प्रोग्रामिंग भाषा कुछ मात्रा में जरूरी प्रोग्रामिंग का समर्थन करती है। यह कहने के लिए कि एक रेखा कहाँ है जो एक कार्यात्मक भाषा है और जो एक अनिवार्य भाषा है, जो सांस्कृतिक पूर्वाग्रहों और लोकप्रिय हठधर्मिता से निर्देशित है?

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


1
IMO संदर्भ गिनती है कचरा संग्रहण, और एक ढेर होने मतलब यह नहीं है कि उन केवल विकल्प वैसे भी कर रहे हैं। सी मॉलस्कॉप्स और एक ढेर का उपयोग करके एमएफआरएस, लेकिन कोई मानक (मानक) कचरा कलेक्टर नहीं है और केवल संदर्भ-मायने रखता है यदि आप ऐसा करने के लिए कोड लिखते हैं। C ++ लगभग एक ही है - इसमें (मानक के रूप में, C ++ 11 में) स्मार्ट पॉइंटर्स इन बिल्ट इन रेफरेंस काउंटिंग हैं, लेकिन आप अभी भी मैन्युअल नया कर सकते हैं और डिलीट कर सकते हैं यदि आपको वास्तव में जरूरत है।
स्टीव 314

यह दावा करने का एक सामान्य कारण है कि संदर्भ गणना कचरा संग्रहण नहीं है, यह संदर्भ चक्र एकत्र करने में विफल रहता है। यह निश्चित रूप से सरल कार्यान्वयन के लिए लागू होता है (शायद C ++ स्मार्ट पॉइंटर्स सहित - मैंने जांच नहीं की है) लेकिन यह हमेशा मामला नहीं होता है। कम से कम एक जावा वर्चुअल मशीन (आईबीएम, आईआईआरसी द्वारा) ने अपने कचरा संग्रहण के आधार के रूप में संदर्भ गिनती का उपयोग किया।
स्टीव 314
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.