अधिकांश प्रोग्रामिंग भाषाएं केवल फ़ंक्शन से एकल मान वापस करने का समर्थन क्यों करती हैं? [बन्द है]


118

क्या कोई कारण है कि अधिकांश (?) प्रोग्रामिंग भाषाओं में फ़ंक्शंस किसी भी संख्या में इनपुट मापदंडों का समर्थन करने के लिए डिज़ाइन किए गए हैं, लेकिन केवल एक रिटर्न मान?

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

क्या इसके लिए कोई स्पष्टीकरण है?


40
क्योंकि आप एक सरणी वापस कर सकते हैं ...
nathan hayfield

6
तो क्यों न केवल एक तर्क की अनुमति दें? मुझे संदेह है कि यह भाषण से बंधा है। कुछ उपाय करें, उन्हें एक चीज में स्मूच करें जिसे आप सौभाग्यशाली / दुर्भाग्यपूर्ण मानते हैं। वापसी लगभग एक राय की तरह है। "यह" आप "इन" के साथ क्या करते हैं।
एरिक रेपेन

30
मेरा मानना ​​है कि अजगर का दृष्टिकोण काफी सरल और सुरुचिपूर्ण है: जब आपको कई मूल्यों को वापस करना होता है तो बस एक टपल लौटाते हैं: def f(): return (1,2,3)और फिर आप टपल को "विभाजित" करने के लिए टपल-अनपैकिंग का उपयोग कर सकते हैं a,b,c = f() #a=1,b=2,c=3:। कोई सरणी बनाने और मैन्युअल रूप से निकालने वाले तत्वों की आवश्यकता नहीं है, किसी भी नए वर्ग को परिभाषित करने की आवश्यकता नहीं है।
बकुरीउ

7
मैं आपको सूचित कर सकता हूं कि मतलाब के पास वापसी मूल्यों की एक चर संख्या है। आउटपुट तर्कों की संख्या को कॉलिंग सिग्नेचर (जैसे [a, b] = f()बनाम [a, b, c] = f()) द्वारा निर्धारित किया जाता है और इसके fद्वारा प्राप्त किया जाता है nargout। मैं मतलूब का बहुत बड़ा प्रशंसक नहीं हूं लेकिन यह वास्तव में कई बार काम आता है।
gerrit

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

जवाबों:


58

कुछ भाषाएं, जैसे पायथन , कई रिटर्न वैल्यू को मूल रूप से सपोर्ट करती हैं, जबकि कुछ भाषाएं जैसे C # उन्हें अपने बेस लाइब्रेरी के जरिए सपोर्ट करती हैं।

लेकिन सामान्य तौर पर, यहां तक ​​कि उन भाषाओं में भी जो उनका समर्थन करते हैं, कई बार वापसी मूल्यों का उपयोग नहीं किया जाता है क्योंकि वे मैला होते हैं:

  • कई मान लौटाने वाले कार्य स्पष्ट रूप से नाम के लिए कठिन हैं ।
  • रिटर्न मानों के क्रम में गलती करना आसान है

    (password, username) = GetUsernameAndPassword()  
    

    (इसी कारण से, बहुत से लोग किसी फ़ंक्शन के लिए बहुत सारे पैरामीटर होने से बचते हैं; कुछ लोग यह भी कहते हैं कि किसी फ़ंक्शन को कभी भी एक ही प्रकार के दो पैरामीटर नहीं होने चाहिए!)

  • ओओपी भाषाओं में पहले से ही कई रिटर्न-वैल्यूज़ का बेहतर विकल्प है: कक्षाएं।
    वे अधिक दृढ़ता से टाइप किए गए हैं, वे रिटर्न मानों को एक तार्किक इकाई के रूप में वर्गीकृत करते हैं, और वे सभी उपयोगों के अनुरूप रिटर्न मानों के नाम (गुण) रखते हैं।

एक ही स्थान पर वे कर रहे हैं बहुत सुविधाजनक (अजगर) की तरह भाषाओं जहां एक समारोह से कई वापसी मान एक और करने के लिए कई इनपुट पैरामीटर के रूप में इस्तेमाल किया जा सकता है। लेकिन, उपयोग-मामले जहां एक वर्ग का उपयोग करने की तुलना में यह एक बेहतर डिज़ाइन है, वे बहुत पतले हैं।


50
यह कहना कठिन है कि टपल लौटाने से कई चीजें लौट रही हैं। इसकी एक टुकड़ी लौट रही है । आपने जो कोड लिखा है, उसे कुछ सेंसिटिव चीनी का उपयोग करके साफ-सुथरे तरीके से अनपैक करें।

10
@ लेगो: मुझे कोई अंतर दिखाई नहीं दे रहा है - एक ट्यूपल परिभाषा के अनुसार कई मान है। यदि आप ऐसा नहीं करते हैं, तो आप "एकाधिक रिटर्न मान" पर क्या विचार करेंगे?
ब्लूराजा - डैनी पफ्लुगुएफ्ट

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

19
... मैंने कभी यह दावा नहीं किया कि अन्य चीजों के लिए टुपल्स का उपयोग नहीं किया जा सकता है। लेकिन यह तर्क देते हुए कि "पायथन कई वापसी मूल्यों का समर्थन नहीं करता है, यह ट्यूपल्स का समर्थन करता है" बस बेहद व्यर्थ पांडित्य है। यह अभी भी एक सही उत्तर है।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

14
न तो ट्यूपल और न ही कक्षाएं "कई मूल्य" हैं।
एंड्रेस एफ।

54

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

यह नहीं बदला है क्योंकि प्रोग्रामर ने outअजीब निर्माण करने के लिए पैरामीटर पाए हैं जो केवल सीमित परिदृश्य में उपयोगी हैं। कई अन्य चीजों की तरह, समर्थन वहाँ नहीं है क्योंकि आवश्यकता / मांग नहीं है।


5
@FrustratedWithFormsDesigner - यह हाल ही के एक प्रश्न में थोड़ा ऊपर आया । मैं एक हाथ पर भरोसा कर सकता हूं कि मैं 20 वर्षों में कई आउटपुट चाहता हूं।
तेलस्टीन जूल

61
गणित में फ़ंक्शंस और अधिकांश प्रोग्रामिंग भाषाओं में फ़ंक्शंस दो बहुत अलग जानवर हैं।
tdammers

17
@ शुरुआती दिनों में, वे विचार में बहुत समान थे। फोरट्रान, पास्कल और उस तरह जहां कंप्यूटिंग वास्तुकला की तुलना में गणित से बहुत अधिक प्रभावित है।

9
@ दोस्त - ऐसा कैसे? मेरा मतलब है कि अधिकांश भाषाओं के लिए यह अंत में लैम्ब्डा कैलकुलस को उबालता है - एक इनपुट, एक आउटपुट, कोई साइड इफेक्ट नहीं। बाकी सब कुछ एक सिमुलेशन / हैक है जो शीर्ष पर है। प्रोग्रामिंग फ़ंक्शन इस अर्थ में शुद्ध नहीं हो सकते हैं कि कई इनपुट समान आउटपुट प्राप्त कर सकते हैं, लेकिन भावना है।
तेलेस्टीन

16
@SteveEvers: यह दुर्भाग्यपूर्ण है कि "फंक्शन" नाम को अधिक उपयुक्त "प्रक्रिया" या "रूटीन" के बजाय अनिवार्य प्रोग्रामिंग में ले लिया गया। कार्यात्मक प्रोग्रामिंग में, एक फ़ंक्शन गणितीय कार्यों से बहुत अधिक निकटता जैसा दिखता है।
तदमर्स

35

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

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

उन प्रकारों के कार्यों के बारे में, जिनके बारे में आप बात कर रहे हैं (अर्थात ऐसे कार्य जो कई प्रकारों को लौटाते हैं, विभिन्न प्रकारों के ) मैं इसे थोड़े अलग तरीके से देखता हूं जैसे कि: मैं बेहतर डिजाइन के लिए वर्कअराउंड के रूप में आउट परमेस की आवश्यकता / उपयोग को देखता हूं। अधिक उपयोगी डेटा संरचना। उदाहरण के लिए, मैं पसंद करूंगा कि क्या *.TryParse(...)विधियाँ Maybe<T>एक आउट परम का उपयोग करने के बजाय एक साधु को लौटा दें । इस कोड को F # में सोचें:

let s = "1"
match tryParse s with
| Some(i) -> // do whatever with i
| None -> // failed to parse

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

अन्य परिदृश्यों के लिए - जिन्हें मैं याद नहीं कर सकता - एक साधारण टपल पर्याप्त है।


1
इसके अलावा, मैं वास्तव में C # में लिखने में सक्षम var (value, success) = ParseInt("foo");होना चाहूंगा : जो कि संकलित समय-प्रकार की जाँच की जाएगी क्योंकि (int, bool) ParseInt(string s) { }घोषित किया गया था। मुझे पता है कि यह जेनेरिक के साथ किया जा सकता है, लेकिन फिर भी यह एक अच्छी भाषा को जोड़ देगा।
डेसपेयर जूल

10
@GrimaceofDespair जो आप वास्तव में चाहते हैं वह सिंटेक्स को नष्ट कर रहा है, न कि कई रिटर्न वैल्यू।
डोमिनिक जूल

2
@warren: हाँ। यहाँ देखें और ध्यान दें कि ऐसा समाधान निरंतर नहीं होगा: en.wikipedia.org/wiki/Well-definition
स्टीवन एवर्स

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

1
@MichaelSiler (मैं आपकी टिप्पणी से सहमत हूं) लेकिन कृपया ध्यान दें कि तर्क प्रतिवर्ती है: "तर्क जो प्रोग्राम फ़ंक्शन कई मानों को वापस कर सकते हैं क्योंकि वे एक एकल टपल मूल्य वापस कर सकते हैं या तो बहुत सम्मोहक नहीं हैं" :)
एंड्रेस एफ

23

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


आह! विस्तार से बहुत दिलचस्प बिंदु। +1!
स्टीवन एवर्स

यह स्वीकृत उत्तर होना चाहिए। आमतौर पर लोग टारगेट मशीनों के बारे में सोचते हैं जब उन्होंने कंपाइलर का निर्माण किया। एक और सादृश्य यह है कि हमारे पास int, float, char / string इत्यादि हैं, क्योंकि यह लक्ष्य मशीन द्वारा समर्थित है। यहां तक ​​कि अगर लक्ष्य नंगे धातु (जैसे jvm) नहीं है, तो भी आप बहुत अधिक अनुकरण न करके सभ्य प्रदर्शन प्राप्त करना चाहते हैं।
imel96

26
... आप किसी फ़ंक्शन से कई मानों को वापस करने के लिए कॉलिंग कन्वेंशन को आसानी से परिभाषित कर सकते हैं, लगभग उसी तरह से आप फ़ंक्शन के लिए कई मानों को पास करने के लिए कॉलिंग कन्वेंशन को परिभाषित कर सकते हैं। यह कोई उत्तर नहीं है। -1
ब्लूराजा - डैनी पफ्लुगुएट

2
यह जानना दिलचस्प होगा कि क्या स्टैक-आधारित निष्पादन इंजन (जेवीएम, सीएलआर) ने कभी-कभी कई वापसी मूल्यों पर विचार / अनुमति दी है .. यह काफी आसान होना चाहिए; फोन करने वाले को सही मानों को पॉप करना होता है, ठीक उसी तरह जैसे वह सही संख्या में तर्कों को आगे बढ़ाता है!
लोरेंजो डेमेटे

1
@David नहीं, cdecl (सैद्धांतिक रूप से) असीमित संख्या में पैरामीटर की अनुमति देता है ( यही कारण है कि varargs फ़ंक्शन संभव हैं) । हालाँकि कुछ सी-कंपाइलर आपको प्रति फ़ंक्शन कई दर्जन या सौ तर्क तक सीमित कर सकते हैं, जो मुझे लगता है कि अभी भी उचित -_- से अधिक है
ब्लूराजा - डैनी पफ्लुगुएफ्ट

18

बहुत सारे उपयोग के मामले जहां आपने पूर्व में कई रिटर्न मानों का उपयोग किया होगा, वे अब आधुनिक भाषा सुविधाओं के साथ आवश्यक नहीं हैं। त्रुटि कोड वापस करना चाहते हैं? एक अपवाद फेंकें या वापस लौटें Either<T, Throwable>। वैकल्पिक परिणाम वापस करना चाहते हैं? एक वापसी Option<T>। कई प्रकारों में से एक लौटना चाहते हैं? एक Either<T1, T2>या एक टैग की गई यूनियन लौटें ।

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

यहाँ उन भाषाओं के कुछ उदाहरण दिए गए हैं जो कई मूल्यों को लौटाने का समर्थन नहीं करते हैं। मैं वास्तव में यह नहीं देखता कि कई वापसी मूल्यों के लिए समर्थन जोड़ने से उन्हें एक नई भाषा सुविधा की लागत को ऑफसेट करने के लिए बहुत अधिक अभिव्यंजक हो जाएगा।

माणिक

def foo; return 1, 2, 3 end

one, two, three = foo

one
# => 1

three
# => 3

अजगर

def foo(): return 1, 2, 3

one, two, three = foo()

one
# >>> 1

three
# >>> 3

स्काला

def foo = (1, 2, 3)

val (one, two, three) = foo
// => one:   Int = 1
// => two:   Int = 2
// => three: Int = 3

हास्केल

let foo = (1, 2, 3)

let (one, two, three) = foo

one
-- > 1

three
-- > 3

Perl6

sub foo { 1, 2, 3 }

my ($one, $two, $three) = foo

$one
# > 1

$three
# > 3

1
मुझे लगता है कि एक पहलू यह है कि, कुछ भाषाओं में (जैसे मतलाब), एक फ़ंक्शन लचीला हो सकता है कि यह कितने मूल्यों में लौटता है; ऊपर मेरी टिप्पणी देखें । मतलाब मुझे पसंद नहीं है, लेकिन यह कुछ (शायद एकमात्र) सुविधा में से एक है जो मतलाब से उदाहरण के लिए पायथन में पोर्ट करते समय याद आती है।
जेरिट

1
लेकिन पायथन या रूबी जैसी गतिशील भाषाओं का क्या? मान लीजिए कि मैं मतलाब sortफ़ंक्शन की तरह कुछ लिखता हूं : sorted = sort(array)केवल क्रमबद्ध सरणी [sorted, indices] = sort(array)देता है , जबकि दोनों देता है। एकमात्र ऐसा तरीका है जिसके बारे में मैं सोच सकता हूं कि पायथन sortमें sort(array, nout=2)या की तर्ज पर एक ध्वज को पारित करना होगा sort(array, indices=True)
जेरिट

2
@ माइक कैलीनी मुझे ऐसा नहीं लगता। एक फ़ंक्शन यह बता सकता है कि फ़ंक्शन कितने आउटपुट तर्कों को कहा जाता है ( [a, b, c] = func(some, thing)) और तदनुसार कार्य करता है। यह उपयोगी है, उदाहरण के लिए, यदि पहले आउटपुट तर्क की गणना करना सस्ता है, लेकिन दूसरे की गणना करना महंगा है। मैं ऐसी किसी अन्य भाषा से परिचित नहीं हूँ जहाँ Matlabs के बराबर nargoutरन-टाइम उपलब्ध हो।
घाट

1
@ पायथन में सही समाधान यह लिखना है sorted, _ = sort(array):।
मील्स राउत

1
@ माइल्सआउट: और sortफ़ंक्शन यह बता सकता है कि सूचकांकों की गणना करने की आवश्यकता नहीं है? यह अच्छा है, मुझे नहीं पता था।
जोर्ग डब्ल्यू मित्तग

12

असली कारण यह है कि एक एकल वापसी मूल्य इतना लोकप्रिय है कि कई भाषाओं में उपयोग किया जाता है। किसी भी भाषा में जहां आप एक अभिव्यक्ति हो सकते हैं जैसे कि x + 1आप पहले से ही एकल रिटर्न मानों के संदर्भ में सोच रहे हैं क्योंकि आप अपने सिर में एक अभिव्यक्ति का मूल्यांकन करके इसे टुकड़ों में तोड़ते हैं और प्रत्येक टुकड़े का मूल्य तय करते हैं। आप देखें xऔर तय करें कि यह मान 3 है (उदाहरण के लिए), और आप 1 को देखते हैं और फिर आप को देखते हैंx + 1और यह तय करने के लिए सभी को एक साथ रखा है कि पूरे का मूल्य 4. अभिव्यक्ति के प्रत्येक वाक्य-रचना भाग का एक मूल्य है, किसी अन्य मान का नहीं; यह अभिव्यक्ति का प्राकृतिक शब्दार्थ है जिसे हर कोई उम्मीद करता है। जब कोई फ़ंक्शन मानों की एक जोड़ी लौटाता है, तब भी यह वास्तव में एक मान लौटा रहा है जो दो मूल्यों का काम कर रहा है, क्योंकि एक फ़ंक्शन का विचार जो दो मूल्यों को लौटाता है जो किसी भी तरह से एक संग्रह में लिपटे नहीं हैं, बहुत अजीब है।

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

पर्ल एक और भाषा है जो कभी-कभी कार्य कर सकती है जैसे फ़ंक्शन कई मानों को वापस कर रहे हैं, भले ही इसे आमतौर पर केवल एक सूची वापस करने पर विचार किया जाता है। जिस तरह से पर्ल में "इंटरपोलेट" की सूची हमें सूची देती है, (1, foo(), 3)जिसमें 3 तत्व हो सकते हैं, क्योंकि अधिकांश लोग जो पर्ल को नहीं जानते हैं, वे उम्मीद करेंगे, लेकिन आसानी से केवल 2 तत्व, 4 तत्व या किसी भी अधिक संख्या के आधार पर तत्व हो सकते हैं। foo()। पर्ल में सूचियाँ चपटी हैं ताकि वाक्य-रचना सूची में हमेशा सूची के शब्दार्थ न हों; यह एक बड़ी सूची का एक टुकड़ा मात्र हो सकता है।

फ़ंक्शंस का एक और तरीका है कई मानों को वापस करना एक वैकल्पिक अभिव्यक्ति शब्दार्थ है जहाँ किसी भी अभिव्यक्ति में कई मान हो सकते हैं और प्रत्येक मान एक संभावना का प्रतिनिधित्व करता है। x + 1फिर से लें , लेकिन इस बार कल्पना करें कि xदो मान {3, 4} हैं, तो मानों का मान x + 1{4, 5} होगा, और मानों का मान x + x{6, 8} होगा, या शायद {6, 7, 8} होगा। , इस बात पर निर्भर करता है कि क्या एक मूल्यांकन के लिए कई मूल्यों का उपयोग करने की अनुमति है x। इस तरह की एक भाषा का उपयोग कर लागू किया जा सकता है जैसे प्रोलॉग का उपयोग बहुत कुछ करने के लिए प्रोलॉग क्वेरी का कई उत्तर देने के लिए करता है।

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


9

जैसा कि इस उत्तर में सुझाया गया है , यह हार्डवेयर समर्थन की बात है, हालांकि भाषा डिजाइन में परंपरा भी एक भूमिका निभाती है।

जब कोई फ़ंक्शन वापस आता है तो यह एक विशिष्ट रजिस्टर में रिटर्निंग ऑब्जेक्ट के लिए एक पॉइंटर छोड़ देता है

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

इन पहली भाषाओं ने उन भाषाओं के डिजाइन पर बहुत अधिक प्रभाव डाला, जो उनके पीछे थे, हालांकि एकमात्र जो कई मूल्यों को लौटाता था, लिस्प, कभी भी उनकी लोकप्रियता को इकट्ठा नहीं करते थे।

जब C आया, उससे पहले की भाषाओं से प्रभावित होने के दौरान, इसने C को भाषा और इसे लागू करने वाले मशीन कोड के बीच घनिष्ठ संबंध रखते हुए हार्डवेयर संसाधन के कुशल उपयोग पर बहुत ध्यान दिया। इसकी कुछ पुरानी विशेषताएं, जैसे "ऑटो" बनाम "रजिस्टर" चर, उस डिजाइन दर्शन का एक परिणाम हैं।

यह भी बताया जाना चाहिए कि विधानसभा की भाषा 80 के दशक तक व्यापक रूप से लोकप्रिय थी, जब अंत में इसे मुख्यधारा के विकास से बाहर किया जाने लगा। संकलक और निर्मित भाषा लिखने वाले लोग असेंबली से परिचित थे , और अधिकांश भाग के लिए, वहाँ जो सबसे अच्छा काम करता था, रखा गया।

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

तो चलिए विधानसभा भाषा की जांच करते हैं। आइए सबसे पहले 6502 को देखें , जो 1975 का एक माइक्रोप्रोसेसर था जिसे Apple II और VIC-20 माइक्रो कंप्यूटर द्वारा प्रसिद्ध किया गया था। यह उस समय की मेनफ्रेम और मिनीकॉम्पैक्टर्स में उपयोग किए जाने की तुलना में बहुत कमजोर था, हालांकि प्रोग्रामिंग भाषाओं की भोर में 20 से 30 साल पहले के पहले कंप्यूटरों की तुलना में शक्तिशाली था।

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

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

यदि आप 6502, 6800 को प्रेरित करने वाले प्रोसेसर को देखते हैं , तो इसके पास एक अतिरिक्त रजिस्टर था, इंडेक्स रजिस्टर (IX), एसपी के रूप में चौड़ा, जो एसपी से मूल्य प्राप्त कर सकता था।

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

SP + 8: param 2
SP + 6: param 1
SP + 4: return address
SP + 2: local 2
SP + 0: local 1

इसे किसी भी समय कहा जा सकता है क्योंकि सभी अस्थायी स्थान स्टैक पर हैं।

8080 , टीआरएस -80 और CP / M आधारित माइक्रो-कंप्यूटरों के एक मेजबान पर इस्तेमाल 6800 के लिए इसी तरह कुछ कर सकते हैं, स्टैक पर सपा को आगे बढ़ाने के लिए और फिर अपने अप्रत्यक्ष रजिस्टर, HL पर यह पॉपिंग से।

यह चीजों को लागू करने का एक बहुत ही सामान्य तरीका है, और इसे अधिक आधुनिक प्रोसेसर पर और भी अधिक समर्थन मिला, बेस पॉइंटर के साथ जो आसान लौटने से पहले सभी स्थानीय चर को डंपिंग बनाता है।

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

इसलिए आमतौर पर जो किया जाता था वह रिटर्न वैल्यू के लिए एक रजिस्टर को जमा करता था । कॉलिंग कोड जानता था कि रिटर्न वैल्यू एक विशेष रजिस्टर में होगी, जिसे तब तक संरक्षित रखना होगा जब तक इसे बचाया या इस्तेमाल नहीं किया जा सकता है।

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

जैसा कि किसी ने कंप्यूटर के साथ अनुभव के पहले छह महीने में असेंबली लैंग्वेज और फोर्थ सीखा, कई रिटर्न वैल्यूज मुझे पूरी तरह से सामान्य लगते हैं। फोर्थ जैसे ऑपरेटर /mod, जो पूर्णांक विभाजन और बाकी को लौटाते हैं , स्पष्ट प्रतीत होते हैं। दूसरी ओर, मैं आसानी से देख सकता हूं कि कोई व्यक्ति जिसका प्रारंभिक अनुभव C मन था, उस अवधारणा को अजीब पाया: यह "कार्य" क्या है की उनकी बाधित उम्मीदों के खिलाफ जाता है।

गणित के लिए ... ठीक है, मैं कंप्यूटर की प्रोग्रामिंग कर रहा था, इससे पहले कि मैं गणित की कक्षाओं में काम करता। वहाँ है सीएस और प्रोग्रामिंग भाषाओं जो गणित से प्रभावित है की एक पूरी अनुभाग वहाँ एक पूरी अनुभाग जो नहीं है, लेकिन, फिर,।

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


@gnat "सूचित करने के लिए" के रूप में "आवश्यक गुणवत्ता प्रदान करने के लिए" का उपयोग जानबूझकर किया गया था।
डैनियल सी। सोबरल

यदि आप इस बारे में दृढ़ता से महसूस करते हैं, तो रोलबैक के लिए स्वतंत्र महसूस करें; मेरे पढ़ने के प्रभाव के अनुसार यहाँ थोड़ा बेहतर बैठता है: "प्रभावित करता है ... एक महत्वपूर्ण तरीके से"
gnat

1
+1 जैसा कि यह इंगित करता है, कि समकालीन सीपीयू के एक प्रचुर मात्रा में रजिस्टर सेट की तुलना में शुरुआती सीपीयू के विरल रजिस्टर की गिनती (कई एबीआई में उपयोग की जाती है, जैसे x64 अबी) एक गेम परिवर्तक हो सकती है और पूर्व में केवल 1 मान वापस करने के लिए मजबूर करने वाले कारण हो सकते हैं। आजकल सिर्फ एक ऐतिहासिक कारण हो सकता है।
BitTickler

मुझे विश्वास नहीं है कि शुरुआती 8-बिट माइक्रो सीपीयू का भाषा डिजाइन पर बहुत अधिक प्रभाव है और किसी भी वास्तुकला में सी या फोरट्रान कॉलिंग सम्मेलनों में किन चीजों की आवश्यकता होती है। फोरट्रान मानता है कि आप सरणी आर्ग्स (मूल रूप से पॉइंटर्स) पास कर सकते हैं। तो पहले से ही आपके पास 6502 जैसी मशीनों पर सामान्य फोरट्रान के लिए प्रमुख कार्यान्वयन समस्याएं हैं, क्योंकि सूचक + सूचकांक के लिए एड्रेसिंग-मोड की कमी के कारण, जैसे आपके उत्तर में चर्चा की गई है और क्यों सी से Z80 संकलक खराब कोड का उत्पादन करते हैं? retrocomputing.SE पर।
पीटर कॉर्ड्स

फोरट्रान, सी की तरह, यह भी मानती है कि आप मनमानी संख्या में आर्ग पास कर सकते हैं, और उनके लिए यादृच्छिक पहुँच और स्थानीय लोगों की एक मनमानी राशि है, है ना? जैसा कि आपने अभी समझाया, आप ऐसा आसानी से 6502 पर नहीं कर सकते हैं क्योंकि स्टैक-रिलेटिव एड्रेसिंग एक चीज नहीं है, जब तक कि आप पुनर्मिलन नहीं छोड़ते। आप उन्हें स्टैटिक स्टोरेज में पॉप कर सकते हैं। यदि आप एक मनमानी arg सूची पास कर सकते हैं, तो आप रिटर्न मानों (जैसे पहले से परे) के लिए अतिरिक्त छिपे हुए पैरामीटर जोड़ सकते हैं जो रजिस्टरों में फिट नहीं होते हैं।
पीटर कॉर्ड्स

7

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

f :: Int -> (Int, Int)
f x = (x - 1, x + 1)

// Even C++ have tuples - see Boost.Graph for use
std::pair<int, int> f(int x) {
  return std::make_pair(x - 1, x + 1);
}

ऊपर दिए गए उदाहरण में, fएक फ़ंक्शन 2 ints लौटा रहा है।

इसी तरह, एमएल, हास्केल, एफ #, आदि भी डेटा संरचनाओं को वापस कर सकते हैं (अधिकांश भाषाओं के लिए पॉइंटर्स बहुत कम-स्तर हैं)। मैंने इस तरह के प्रतिबंध के साथ एक आधुनिक जीपी भाषा के बारे में नहीं सुना है:

data MyValue = MyValue Int Int

g :: Int -> MyValue
g x = MyValue (x - 1, x + 1)

अंत में, outमापदंडों का कार्यात्मक भाषाओं में भी अनुकरण किया जा सकता है IORef। अधिकांश भाषाओं में बाहर चर के लिए कोई देशी समर्थन नहीं होने के कई कारण हैं:

  • अस्पष्ट शब्दार्थ : निम्नलिखित फ़ंक्शन 0, या 1 प्रिंट करता है? मुझे उन भाषाओं का पता है जो 0 प्रिंट करेंगी, और जो 1 प्रिंट करेंगी। उन दोनों के लिए लाभ हैं (प्रदर्शन के मामले में दोनों, साथ ही प्रोग्रामर के मानसिक मॉडल से मेल खाते हैं):

    int x;
    
    int f(out int y) {
      x = 0;
      y = 1;
      printf("%d\n", x);
    }
    f(out x);
    
  • गैर-स्थानीयकृत प्रभाव : जैसा कि ऊपर दिए गए उदाहरण में, आप पा सकते हैं कि आपके पास एक लंबी श्रृंखला हो सकती है और अंतरतम कार्य वैश्विक स्थिति को प्रभावित करता है। सामान्य तौर पर, यह फ़ंक्शन की आवश्यकताओं के बारे में तर्क करना कठिन बनाता है, और यदि परिवर्तन कानूनी है। यह देखते हुए कि अधिकांश आधुनिक प्रतिमान या तो प्रभावों को स्थानीय बनाने की कोशिश करते हैं (ओओपी में इनकैप्सुलेशन) या साइड-इफेक्ट्स (कार्यात्मक प्रोग्रामिंग) को खत्म करते हैं, यह उन प्रतिमानों के साथ टकराव करता है।

  • निरर्थक होने के नाते : यदि आपके पास ट्यूपल्स हैं, तो आपके पास outमापदंडों की कार्यक्षमता का 99% और मुहावरेदार उपयोग का 100% है। यदि आप मिश्रण में संकेत जोड़ते हैं तो आप शेष 1% को कवर करते हैं।

मुझे एक भाषा का नामकरण करने में परेशानी होती है, जो एक ट्यूपल, क्लास या outपैरामीटर (और ज्यादातर मामलों में 2 या अधिक विधियों की अनुमति है) का उपयोग करके कई मान नहीं लौटा सकती ।


+1 यह बताने के लिए कि कैसे कार्यात्मक भाषाएं इसे सुरुचिपूर्ण और दर्द रहित तरीके से संभालती हैं।
एंड्रेस एफ।

1
तकनीकी तौर पर आप अभी भी एक ही मूल्य वापस कर रहे हैं: डी (यह सिर्फ इतना है कि यह एकल मूल्य कई मूल्यों में विघटित करने के लिए तुच्छ है)।
थॉमस ईडिंग

1
मैं कहूंगा कि वास्तविक "आउट" शब्दार्थ के साथ एक पैरामीटर को एक संकलक अस्थायी के रूप में व्यवहार करना चाहिए जो एक विधि द्वारा सामान्य रूप से बाहर निकलने पर गंतव्य पर कॉपी हो जाता है; "इनआउट" शब्दार्थ चर के साथ एक संकलक अस्थायी के रूप में व्यवहार करना चाहिए जो प्रवेश पर पारित चर से लोड किया गया है और बाहर निकलने पर वापस लिखा गया है; "रेफ" शब्दार्थ के साथ एक उपनाम के रूप में व्यवहार करना चाहिए। सी # के तथाकथित "आउट" पैरामीटर वास्तव में "रेफ" पैरामीटर हैं, और इस तरह से व्यवहार करते हैं।
सुपरकैट

1
टपल "वर्कअराउंड" भी मुफ्त में नहीं आता है। यह अनुकूलन के अवसरों को अवरुद्ध करता है। यदि कोई ABI मौजूद था जो CPU रजिस्टरों में N रिटर्न वैल्यू को वापस करने की अनुमति देता है, तो कंपाइल वास्तव में ऑप्टिमाइज़ कर सकता है, बजाय टुपल इंस्टेंस के और इसे बनाने के।
BitTickler

1
@BitTickler अगर आप ABI को नियंत्रित करते हैं, तो रजिस्टरों द्वारा पारित किए जाने वाले संरचना के पहले n क्षेत्रों को वापस लाने से कुछ नहीं होता है।
मैकीज पाईचोटका

6

मुझे लगता है कि यह भावों के कारण है , जैसे कि (a + b[i]) * c

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

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


4

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


3
क्या आप एक उदाहरण प्रदान कर सकते हैं जहां कई रिटर्न स्पष्ट और / या अधिक कुशल कोड प्रदान करते हैं?
स्टीवन एवर्स

3
उदाहरण के लिए, C ++ COM प्रोग्रामिंग में, कई फ़ंक्शन का एक [out]पैरामीटर होता है, लेकिन वस्तुतः सभी एक HRESULT(त्रुटि कोड) वापस करते हैं। यह सिर्फ वहाँ एक जोड़ी पाने के लिए काफी व्यावहारिक होगा। ऐसी भाषाओं में, जिन्हें ट्यूपल्स का अच्छा समर्थन है, जैसे कि पायथन, यह बहुत सारे कोड का उपयोग करता है जो मैंने देखा है।
फेलिक्स डॉमबेक

कुछ भाषाओं में, आप X और Y समन्वय के साथ एक वेक्टर लौटाएंगे , और किसी भी उपयोगी मान को अपवाद के साथ "सफलता" के रूप में गिना जाएगा, संभवतः उस उपयोगी मान को ले जाना, जिसका उपयोग विफलता के लिए किया जा रहा है।
डोपेलग्रेनेर 22

3
गैर-स्पष्ट तरीकों से वापसी के मूल्य में एन्कोडिंग जानकारी को समाप्त करने का समय - यानी; नकारात्मक मान त्रुटि कोड हैं, सकारात्मक मान परिणाम हैं। युक। हैश टेबल पर पहुंचना, यह इंगित करने के लिए हमेशा गड़बड़ होता है कि आइटम पाया गया था और आइटम को वापस भी करता है।
ddyer

@SteveEvers मतलाब sortफ़ंक्शन आम तौर पर एक सरणी को सॉर्ट करता है sorted_array = sort(array):। कभी-कभी मुझे भी इसी सूचक की आवश्यकता होती है [sorted_array, indices] = sort(array):। कभी-कभी मैं केवल सूचकांक चाहता हूं : [~, indices]= सॉर्ट (एरे) . The function सॉर्ट` वास्तव में बता सकता है कि कितने आउटपुट तर्क की आवश्यकता है, इसलिए यदि 1 की तुलना में 2 आउटपुट के लिए अतिरिक्त कार्य की आवश्यकता है, तो यह केवल उन आउटपुट की गणना कर सकता है यदि आवश्यक हो।
gerrit

2

अधिकांश भाषाओं में जहां फ़ंक्शंस समर्थित हैं, आप कहीं भी एक फ़ंक्शन कॉल का उपयोग कर सकते हैं जहां उस प्रकार का एक चर इस्तेमाल किया जा सकता है: -

x = n + sqrt(y);

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


5
बस अनुचित कार्यों का उपयोग न करें। यह उन कार्यों से उत्पन्न "समस्या" से अलग नहीं है, जो बिना मान लौटाते हैं, या गैर-संख्यात्मक मान लौटाते हैं।
ddyer

3
मैंने जिन भाषाओं का उपयोग किया है, वे कई रिटर्न मान प्रदान करते हैं (SciLab, उदाहरण के लिए), पहला रिटर्न मान विशेषाधिकार प्राप्त है, और उन मामलों में उपयोग किया जाएगा जहां केवल एक मान की आवश्यकता है। तो वहाँ कोई वास्तविक समस्या नहीं है।
फोटॉन

और यहां तक ​​कि जब वे नहीं हैं, जैसे कि पायथन foo()[0]
टुपल अनपैकिंग के

वास्तव में, यदि कोई फ़ंक्शन 2 मान लौटाता है, तो यह वापसी प्रकार 2 मान है, एकल मान नहीं। प्रोग्रामिंग भाषा को आपके दिमाग को नहीं पढ़ना चाहिए।
मार्क ई। हासे

1

मैं सिर्फ हार्वे के उत्तर पर निर्माण करना चाहता हूं। मैंने मूल रूप से एक न्यूज टेक साइट (arstechnica) पर यह प्रश्न पाया और एक अद्भुत स्पष्टीकरण पाया कि मुझे वास्तव में इस प्रश्न का मूल उत्तर लगता है और अन्य सभी उत्तरों (हार्वे को छोड़कर) से इसकी कमी है:

फ़ंक्शन से एकल रिटर्न की उत्पत्ति मशीन कोड में निहित है। मशीन कोड स्तर पर, एक फ़ंक्शन ए (संचायक) रजिस्टर में एक मूल्य वापस कर सकता है। स्टैक पर कोई अन्य रिटर्न मान होगा।

एक भाषा जो दो रिटर्न मानों का समर्थन करती है, इसे मशीन कोड के रूप में संकलित करेगी जो एक रिटर्न देता है, और दूसरा स्टैक पर रखता है। दूसरे शब्दों में, दूसरा वापसी मूल्य वैसे भी एक आउट पैरामीटर के रूप में समाप्त होगा।

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

प्रोग्रामिंग भाषा के निर्माण में कुछ औचित्य है जो कोड संकलित और चलने पर वास्तव में क्या होगा, इसके लिए कुछ समानता रखते हैं।


यदि निम्न-स्तरीय भाषाओं जैसे C ने प्रथम श्रेणी की सुविधा के रूप में कई रिटर्न मानों का समर्थन किया है, तो C कॉलिंग कन्वेंशनों में कई रिटर्न-वैल्यू रजिस्टर शामिल होंगे, उसी तरह जो 6 रजिस्टरों तक का उपयोग x86 में पूर्णांक / पॉइंटर फ़ंक्शन आर्गन्स को पारित करने के लिए किया जाता है। 64 सिस्टम वी एबीआई। (वास्तव में x86-64 SysV RDX में पैक किए गए 16 बाइट्स के लिए रिटर्न स्ट्रक्चर: RAX रजिस्टर पेयर है। यह अच्छा है अगर स्ट्रक्चर को सिर्फ लोड किया गया और स्टोर किया जाएगा, लेकिन अतिरिक्त अनपैकिंग की लागत अलग-अलग सदस्यों में भी होती है। अगर वे 64 बिट्स से अधिक
संकरे हैं

स्पष्ट सम्मेलन RAX होगा, फिर आर्ग-पासिंग regs। (RDI, RSI, RDX, RCX, R8, R9)। या Windows x64 सम्मेलन में, RCX, RDX, R8, R9। लेकिन चूँकि C में मूल रूप से कई रिटर्न मान नहीं हैं, इसलिए C ABI / कॉलिंग कन्वेंशन केवल विस्तृत पूर्णांकों और कुछ संरचनाओं के लिए कई रिटर्न रजिस्टर निर्दिष्ट करते हैं। एआरएम® आर्किटेक्चर के लिए प्रक्रिया कॉल मानक देखें : 2 अलग, लेकिन एआरएम पर 2 रिटर्न मान प्राप्त करने के लिए कुशल एएसएम बनाने के लिए संकलक प्राप्त करने के लिए एक विस्तृत इंट का उपयोग करने के उदाहरण के लिए संबंधित रिटर्न मान
पीटर कॉर्ड्स

-1

इसकी शुरुआत गणित से हुई। फोरट्रान, "फॉर्मूला ट्रांसलेशन" के लिए नामित किया गया पहला कंपाइलर था। FORTRAN था और भौतिकी / गणित / इंजीनियरिंग के लिए उन्मुख है।

COBOL, लगभग पुराने जैसा, कोई स्पष्ट वापसी मूल्य नहीं था; यह मुश्किल से सबरूटीन था। तब से यह ज्यादातर जड़ता में है।

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


4
यह पूछे गए सवाल का जवाब नहीं देता है
gnat

मेरे लिए @gnat यह जवाब देता है। OTOH पहले से ही इसे समझने के लिए कुछ पृष्ठभूमि की आवश्यकता है, और उस व्यक्ति को सवाल पूछने की संभावना नहीं होगी ...
Net

@Net को शायद ही यह पता लगाने के लिए बहुत पृष्ठभूमि की आवश्यकता है कि "फोरट्रान ... पहला कंपाइलर" जैसे बयान कुल गड़बड़ हैं। यह गलत भी नहीं है। बस इस "उत्तर" के बाकी हिस्सों की तरह
gnat

लिंक का कहना है कि पहले संकलक के प्रयास थे, लेकिन यह कि "आईबीएम में जॉन बैकस के नेतृत्व वाली फोरट्रान टीम को आम तौर पर 1957 में पहला पूर्ण कंपाइलर पेश करने का श्रेय दिया जाता है"। पूछा गया प्रश्न केवल एक ही क्यों था? जैसा मैंने कहा। यह ज्यादातर गणित और जड़ता था। शब्द "फ़ंक्शन" की गणितीय परिभाषा के लिए ठीक एक परिणाम मूल्य की आवश्यकता है। तो यह एक परिचित रूप था।
रिकी डिसे

-2

प्रोसेसर मशीन के निर्देशों और फंक्शन कॉल को मशीन कोड से कैसे प्राप्त किया जाता है: उदाहरण के लिए, C -> असेंबली -> मशीन से यह पता चलता है कि यह संभवत: विरासत के साथ अधिक है।

कैसे प्रोसेसर्स फंक्शन कॉल्स करते हैं

पहले प्रोग्राम मशीन कोड में लिखे गए और फिर बाद में असेंबली में। प्रोसेसर ने वर्तमान रजिस्टरों की एक प्रति को स्टैक पर धकेलकर फ़ंक्शन कॉल का समर्थन किया। फ़ंक्शन से लौटने पर स्टैक से रजिस्टरों के सहेजे गए सेट को पॉप किया जाएगा। आमतौर पर एक रजिस्टर को अछूता छोड़ दिया जाता था ताकि रिटर्निंग फंक्शन को मान वापस किया जा सके।

अब, क्यों प्रोसेसर इस तरह से डिज़ाइन किए गए थे ... यह संभवतः संसाधन की कमी का सवाल था।

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