मूल्य से इतनी अधिक भाषाएं क्यों पारित की गई हैं?


36

यहां तक ​​कि ऐसी भाषाएं जहां आपके पास स्पष्ट सूचक हेरफेर है जैसे C यह हमेशा मूल्य द्वारा पारित किया जाता है (आप उन्हें संदर्भ द्वारा पारित कर सकते हैं लेकिन यह डिफ़ॉल्ट व्यवहार नहीं है)।

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


5
void acceptEntireProgrammingLanguageByValue(C++);
थॉमस ईडिंग

4
और बुरा हो सकता था। कुछ पुरानी भाषाओं ने भी नाम से
पुकारने

25
दरअसल, सी में आप संदर्भ से नहीं गुजर सकते। आप एक पॉइंटर को वैल्यू द्वारा पास कर सकते हैं , जो पास-बाय-रेफरेंस के समान है, लेकिन एक ही चीज से नहीं। C ++ में, हालांकि, आप संदर्भ से गुजर सकते हैं।
मेसन व्हीलर

@ मेसन व्हीलर आप अधिक विस्तार कर सकते हैं या कुछ लिंक जोड़ सकते हैं, अपने कथन को स्पष्ट न करें क्योंकि मैं सी / सी ++ गुरु नहीं हूं, सिर्फ एक नियमित प्रोग्रामर, धन्यवाद
बेटलिस्टा

1
@Betlista: संदर्भ द्वारा पारित के साथ, आप एक स्वैप दिनचर्या है कि इस तरह दिखता है लिख सकते हैं temp := a; a := b; b := temp;और जब यह देता है, के मूल्यों aऔर bबदली की जाएगी। सी में ऐसा करने का कोई तरीका नहीं है; आप की ओर इशारा पास करना aऔर bऔर swapदिनचर्या मूल्यों उनके द्वारा इंगित पर कार्रवाई करने के है।
मेसन व्हीलर

जवाबों:


58

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

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

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


4
+1 संकेत बिंदुओं को क्षय करने के लिए एक उल्लेखनीय अपवाद प्रस्तुत करता है, लेकिन समग्र विवरण अच्छा है।
dasblinkenlight

6
@dasblinkenlight: सरणियाँ C में एक दुख की बात है :(
Matthieu M.

55

कॉल-बाय-वैल्यू और कॉल-बाय-रेफरेंस कार्यान्वयन तकनीकें हैं जो कि बहुत समय पहले पैरामीटर-पासिंग मोड के लिए गलत थीं।

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

ALGOL कॉल-बाय-नेम और कॉल-बाय-वैल्यू के साथ आया। कॉल-बाय-वैल्यू उन चीजों के लिए था जिन्हें बदला नहीं जाना चाहिए था (इनपुट पैरामीटर्स)। कॉल-बाय-नाम आउटपुट पैरामीटर के लिए था। कॉल-बाय-नाम एक प्रमुख क्रॉक निकला, और ALGOL 68 ने इसे गिरा दिया।

PASCAL ने कॉल-बाय-वैल्यू और कॉल-बाय-रेफरेंस प्रदान किया। यह प्रोग्रामर के लिए संकलक को यह बताने के लिए कोई रास्ता नहीं प्रदान करता था कि वह पैरामीटर स्टैक को उड़ाने से बचने के लिए संदर्भ द्वारा एक बड़ी वस्तु (आमतौर पर एक सरणी) से गुजर रहा था, लेकिन यह कि वस्तु को बदला नहीं जाना चाहिए।

PASCAL ने भाषा डिजाइन lexicon के लिए संकेत जोड़े।

C ने कॉल-बाय-वैल्यू प्रदान की, और मेमोरी में एक मनमाना ऑब्जेक्ट को पॉइंटर वापस करने के लिए एक कीचड़ ऑपरेटर को परिभाषित करके कॉल-बाय-रेफरेंस को सिम्युलेटेड किया।

बाद में भाषाओं ने सी की नकल की, ज्यादातर क्योंकि डिजाइनरों ने कभी और कुछ नहीं देखा था। शायद यही कारण है कि कॉल-बाय-वैल्यू इतनी लोकप्रिय है।

C ++ ने कॉल-बाय-संदर्भ प्रदान करने के लिए C कीचड़ के ऊपर एक कीचड़ जोड़ा।

अब, कॉल-बाय-वैल्यू बनाम कॉल-बाय-रेफरेंस बनाम कॉल-बाय-पॉइंटर-कल्ज, सी और सी ++ (प्रोग्रामर) के प्रत्यक्ष परिणाम के रूप में कॉन्स्ट पॉइंटर्स और पॉइंटर्स टू कॉन्स्ट (केवल पढ़ने के लिए) के साथ भयानक सिरदर्द होते हैं वस्तुओं।

आद्या इस पूरे बुरे सपने से बचने में कामयाब रही।

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


1
+1। यह एकमात्र ऐसा उत्तर है जो मैंने अब तक यहां देखा है जो वास्तव में प्रश्न का उत्तर देता है और समझ में आता है और इसका उपयोग प्रो-एफपी रैंट के लिए पारदर्शी बहाने के रूप में नहीं करता है।
मेसन व्हीलर

11
+1 के लिए "बाद की भाषाओं ने सी की नकल की, ज्यादातर क्योंकि डिजाइनरों ने कभी और कुछ नहीं देखा था।" हर बार जब मैं एक नई भाषा देखता हूं, तो मैं पहले से थोड़ा अंदर मर जाता हूं।
कामवासना

4
यह प्रोग्रामिंग की बाइबल का पहला वाक्य हो सकता है In the beginning, there was FORTRAN:।

1
एडीए के संबंध में, यदि वैश्विक वैरिएबल को इन / आउट पैरामीटर से पारित किया जाता है, तो क्या भाषा एक नेस्टेड कॉल को जांचने या संशोधित करने से रोक देगी? यदि नहीं, तो मुझे लगता है कि / बाहर और रेफरी मापदंडों के बीच एक स्पष्ट अंतर होगा। व्यक्तिगत रूप से, मैं ऐसी भाषाओं को स्पष्ट रूप से "इन / आउट / इन + आउट" और "वैल्यू / रिफ / न-केयर" के सभी संयोजनों का समर्थन करना चाहता हूं, इसलिए प्रोग्रामर अपने इरादे के अनुसार अधिकतम स्पष्टता प्रदान कर सकते हैं, लेकिन आशावादी कार्यान्वयन में अधिकतम लचीलापन होगा [जब तक कि यह प्रोग्रामर इरादे के साथ जिब हो]।
सुपरैट

2
@ नीकोस यह भी तथ्य है कि 0उपसर्ग हर दूसरे गैर-आधार दस उपसर्ग के साथ असंगत है। यही कारण है कि, सी में कुछ हद तक क्षम्य (और ज्यादातर स्रोत संगत भाषाओं, जैसे सी ++, उद्देश्य सी) हो सकता है अगर अष्टाधारी था केवल विकल्प आधार जब शुरू की, लेकिन जब अधिक आधुनिक भाषाओं दोनों का उपयोग 0xऔर 0शुरू से ही, यह सिर्फ उन्हें खराब लग रही है सावधानीपूर्वक विचार किया।
8bittree

13

संदर्भ के द्वारा पास बहुत ही सूक्ष्म अनपेक्षित दुष्प्रभावों के लिए अनुमति देता है जो कि अनपेक्षित व्यवहार का कारण बनने पर पता लगाने के लिए अगले को असंभव करना बहुत मुश्किल है।

मूल्य, विशेष रूप से final, staticया constइनपुट मापदंडों से गुजरना इस कीड़े के पूरे वर्ग को गायब कर देता है।

अपरिवर्तनीय भाषाएं और भी अधिक निर्धारक और आसान होती हैं, जो इस बात को समझने और समझने में आसान होती हैं कि क्या हो रहा है और एक समारोह से क्या होने की उम्मीद है।


7
यह उन चीजों में से एक है जिन्हें आप 'प्राचीन' वीबी कोड पर डिबग करने की कोशिश के बाद समझ लेते हैं कि सब कुछ डिफ़ॉल्ट रूप से संदर्भ में है।
jfrankcarr

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

4
@MasonWheeler आपके पीछे आने वाले नए-नए किस्सों के बारे में बताएंगे और जो आपने बिना समझे किए उसे कॉपी कर लिया है और उस स्टेट को अप्रत्यक्ष रूप से उस जगह पर हेरफेर करना शुरू कर देते हैं, असली दुनिया हर समय होती है। कम अप्रत्यक्षता एक अच्छी बात है। अपरिवर्तनीय सर्वोत्तम है।

1
@MasonWheeler Swapहैक की तरह सरल उर्फ ​​उदाहरण, एक अस्थायी चर का उपयोग नहीं करते हैं, हालांकि खुद को एक समस्या होने की संभावना नहीं है, यह दिखाने के लिए कि अधिक जटिल उदाहरण कितना कठिन हो सकता है।
मार्क हर्ड

1
@MasonWheeler: फोरट्रान में क्लासिक उदाहरण, जिसके कारण कहा गया कि "वेरिएबल्स की कमी हो सकती है। स्थिरांक नहीं हैं", एक फ़्लोटिंग-पॉइंट स्थिरांक को 3.0 की तरह एक फ़ंक्शन से गुजरता होगा जो पास-इन पैरामीटर को संशोधित करता है। किसी भी फ़्लोटिंग-पॉइंट स्थिरांक के लिए जिसे फ़ंक्शन में पास किया गया था, सिस्टम एक "छिपा हुआ" वैरिएबल बनाएगा, जिसे उचित मूल्य के साथ आरंभीकृत किया गया था और कार्यों के लिए पारित किया जा सकता है। यदि फ़ंक्शन 1.0 को अपने पैरामीटर में जोड़ता है, तो प्रोग्राम में 3.0 का एक मनमाना उपसमुच्चय अचानक 4.0 बन सकता है।
सुपरकैट

8

मूल्य से इतनी अधिक भाषाएं क्यों पारित की गई हैं?

छोटे सबरूटीन्स में बड़े कार्यक्रमों को तोड़ने की बात यह है कि आप स्वतंत्र रूप से सबरूटीन्स के बारे में तर्क कर सकते हैं। दर-दर-संदर्भ इस संपत्ति को तोड़ता है। (जैसा कि साझा उत्परिवर्तनीय स्थिति है।)

यहां तक ​​कि ऐसी भाषाएं जहां आपके पास स्पष्ट सूचक हेरफेर है जैसे C यह हमेशा मूल्य द्वारा पारित किया जाता है (आप उन्हें संदर्भ द्वारा पारित कर सकते हैं लेकिन यह डिफ़ॉल्ट व्यवहार नहीं है)।

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

इसका क्या फ़ायदा है, क्यों इतनी सारी भाषाएं मूल्यों से गुज़री हैं और अन्य क्यों संदर्भ से गुज़री हैं ?

पास-बाय-संदर्भ का उपयोग करने के दो मुख्य कारण हैं:

  1. कई रिटर्न वैल्यू का अनुकरण
  2. दक्षता

व्यक्तिगत रूप से, मुझे लगता है कि # 1 फर्जी है: यह लगभग हमेशा खराब एपीआई और / या भाषा डिजाइन का एक बहाना है:

  1. यदि आपको कई रिटर्न मानों की आवश्यकता है, तो उन्हें अनुकरण न करें, बस एक ऐसी भाषा का उपयोग करें जो उनका समर्थन करती है।
  2. तुम बस के रूप में अच्छी तरह से एक ट्यूपल जैसे कुछ हल्के डेटा संरचना में उन्हें पैकेजिंग द्वारा कई वापसी मूल्यों का अनुकरण कर सकते हैं। यह विशेष रूप से अच्छी तरह से काम करता है अगर भाषा पैटर्न मिलान या विनाशकारी बाइंड का समर्थन करती है। जैसे रूबी:

    def foo
      # This is actually just a single return value, an array: [1, 2, 3]
      return 1, 2, 3
    end
    
    # Ruby supports destructuring bind for arrays: a, b, c = [1, 2, 3]
    one, two, three = foo
    
  3. अक्सर, आपको कई रिटर्न वैल्यू की भी आवश्यकता नहीं होती है। उदाहरण के लिए, एक लोकप्रिय पैटर्न यह है कि सबरूटिन एक त्रुटि कोड देता है और वास्तविक परिणाम को संदर्भ द्वारा वापस लिखा जाता है। इसके बजाय, आपको केवल एक अपवाद फेंक देना चाहिए यदि त्रुटि अप्रत्याशित है या Either<Exception, T>यदि त्रुटि की उम्मीद है तो वापस कर दें। एक अन्य पैटर्न एक बूलियन को वापस करना है जो बताता है कि क्या ऑपरेशन सफल रहा था और संदर्भ द्वारा वास्तविक परिणाम लौटाया गया था। फिर, यदि विफलता अप्रत्याशित है, तो आपको इसके बजाय एक अपवाद फेंकना चाहिए, यदि विफलता की उम्मीद की जाती है, उदाहरण के लिए जब एक शब्दकोश में मूल्य देखते हैं, तो आपको Maybe<T>इसके बजाय वापस लौटना चाहिए ।

पास-दर-संदर्भ पास-दर-मूल्य से अधिक कुशल हो सकता है, क्योंकि आपको मूल्य की प्रतिलिपि बनाने की आवश्यकता नहीं है।

(मुझे लगता है कि हास्केल संदर्भ द्वारा पारित किया गया है, हालांकि मुझे यकीन नहीं है)।

नहीं, हास्केल पास-बाय-संदर्भ नहीं है। न ही यह पास-दर-मूल्य है। दर-दर-संदर्भ और पास-दर-मूल्य दोनों सख्त मूल्यांकन रणनीति हैं, लेकिन हास्केल गैर-सख्त है।

वास्तव में, हास्केल विशिष्टता किसी विशेष मूल्यांकन रणनीति को निर्दिष्ट नहीं करती है । अधिकांश हेकेल कार्यान्वयन कॉल-बाय-नाम और कॉल-बाय-नीड (मिश्रण के साथ कॉल-बाय-नाम का एक प्रकार) का उपयोग करते हैं, लेकिन मानक इसे अनिवार्य नहीं करता है।

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


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

+1 मैं इस बात से पूरी तरह सहमत हूं कि बड़े कार्यक्रमों को छोटे सबरूटीन्स में तोड़ने की बात
रेमी

3

भाषा के कॉलिंग मॉडल, तर्कों के प्रकार और भाषा के मेमोरी मॉडल के आधार पर अलग-अलग व्यवहार होता है।

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

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

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


2

आप एक अभिव्यक्ति को मूल्य से पारित कर सकते हैं, यह स्वाभाविक है। (अस्थायी) संदर्भ द्वारा अभिव्यक्ति पास करना ... अजीब है।


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

2

यदि आप संदर्भ से गुजरते हैं, तो आप वैश्विक मूल्यों के साथ प्रभावी रूप से काम कर रहे हैं, ग्लोबल्स की सभी समस्याओं के साथ (अर्थात् गुंजाइश और अनपेक्षित दुष्प्रभाव)।

ग्लोबल्स की तरह संदर्भ, कभी-कभी फायदेमंद होते हैं, लेकिन वे आपकी पहली पसंद नहीं होने चाहिए।


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