संदर्भात्मक पारदर्शिता

From Vigyanwiki

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

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

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

इतिहास

ऐसा प्रतीत होता है कि इस अवधारणा की उत्पत्ति ल्फ्रेड नॉर्थ व्हाइटहेड और बर्ट्रेंड रसेल की प्रिंसिपिया मैथमैटिका (1910-13) में हुई थी।[2] इसे विश्लेषणात्मक दर्शनशास्र में विलार्ड वान ऑरमैन क्विन द्वारा अपनाया गया था। वर्ड एंड ऑब्जेक्ट (1960) के §30 में क्वीन यह परिभाषा देती है:

नियंत्रण का एक तरीका φ संदर्भात्मक रूप से पारदर्शी है, यदि, जब भी एक एकल शब्द t की घटना किसी शब्द या वाक्य ψ(t) में विशुद्ध रूप से संदर्भित होती है, तो यह युक्त शब्द या वाक्य φ(ψ(t)) में भी पूरी तरह से संदर्भात्मक होती है।

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

उदाहरण और प्रति उदाहरण

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

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

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

अंकगणितीय संक्रियाएं संदर्भात्मक रूप से पारदर्शी होती हैं: उदाहरण के लिए, 5 * 5 को 25 से बदला जा सकता है। वास्तव में, गणितीय अर्थ में सभी फ़ंक्शन संदर्भात्मक रूप से पारदर्शी हैं: sin(x) पारदर्शी है क्योंकि यह हमेशा प्रत्येक विशेष xके लिए समान परिणाम देगा।

पुनर्नियुक्तियाँ पारदर्शी नहीं हैं. उदाहरण के लिए, C एक्सप्रेशन x = x + 1, वेरिएबल xको निर्दिष्ट मान को बदल देता है। यह मानते हुए कि प्रारंभ मेंxका मान 10 है, अभिव्यक्ति के दो लगातार मूल्यांकन क्रमशः 11 और 12 प्राप्त करते हैं। स्पष्ट रूप से, x = x + 1 को 11 या 12 के साथ प्रतिस्थापित करने से एक अलग अर्थ वाला एक प्रोग्राम मिलता है, और इसलिए अभिव्यक्ति संदर्भात्मक रूप से पारदर्शी नहीं है . हालाँकि, किसी फ़ंक्शन को कॉल करना जैसे int plusone(int x) { return x + 1; } पारदर्शी है, क्योंकि यह इनपुट x को अंतर्निहित रूप से नहीं बदलेगा और इस प्रकार इसका कोई अनुषंगी प्रभाव नहीं होगा।

today() पारदर्शी नहीं है, जैसे कि आप इसका मूल्यांकन करते हैं और इसे इसके मूल्य से प्रतिस्थापित करते हैं (मान लीजिए, "Jan 1, 2001"), यदि आप इसे कल चलाएंगे तो आपको वैसा परिणाम नहीं मिलेगा जैसा आपको मिलेगा। ऐसा इसलिए है क्योंकि यह एक राज्य (कंप्यूटर विज्ञान) (तारीख) पर निर्भर करता है।

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

अनिवार्य प्रोग्रामिंग के विपरीत

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

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

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

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

एक और उदाहरण

उदाहरण के तौर पर, आइए दो फ़ंक्शंस का उपयोग करें, एक जो संदर्भित रूप से पारदर्शी है, और दूसरा जो संदर्भात्मक रूप से अपारदर्शी है:

int g = 0;

int rt(int x) {
  return x + 1;
}

int ro(int x) {
  g++;
  return x + g;
}

फ़ंक्शन rt संदर्भित रूप से पारदर्शी है, जिसका अर्थ है कि यदि x == y तो rt(x) == rt(y) उदाहरण के लिए, rt(6) = 7. हालाँकि, हम roके लिए ऐसी कोई बात नहीं कह सकते क्योंकि यह एक वैश्विक चर का उपयोग करता है जिसे यह संशोधित करता है।

ro की संदर्भात्मक अपारदर्शिता कार्यक्रमों के बारे में तर्क करना अधिक कठिन बना देती है। उदाहरण के लिए, मान लें कि हम निम्नलिखित कथन पर तर्क करना चाहते हैं:

int i = ro(x) + ro(y) * (ro(x) - ro(x));

कोई इस कथन को सरल बनाने के लिए प्रलोभित हो सकता है:

int i = ro(x) + ro(y) * 0;
int i = ro(x) + 0;
int i = ro(x);

हालाँकि, यहroके लिए काम नहीं करेगा क्योंकि ro(x) की प्रत्येक घटना का मूल्यांकन एक अलग मान पर होता है। याद रखें कि ro का रिटर्न मान एक वैश्विक मान पर आधारित होता है जिसे पास नहीं किया जाता है और जो ro पर प्रत्येक कॉल पर संशोधित हो जाता है। इसका मतलब यह है कि गणितीय पहचान जैसे कि xx = 0 अब मान्य नहीं है।

ऐसी गणितीय पहचानें rtजैसे संदर्भात्मक रूप से पारदर्शी फंक्शन्स के लिए मान्य होंगी।

हालाँकि, अधिक परिष्कृत विश्लेषण का उपयोग कथन को सरल बनाने के लिए किया जा सकता है:

int tmp = g; int i = x + tmp + 1 + (y + tmp + 2) * (x + tmp + 3 - (x + tmp + 4)); g = g + 4;
int tmp = g; int i = x + tmp + 1 + (y + tmp + 2) * (x + tmp + 3 - x - tmp - 4)); g = g + 4;
int tmp = g; int i = x + tmp + 1 + (y + tmp + 2) * (-1); g = g + 4;
int tmp = g; int i = x + tmp + 1 - y - tmp - 2; g = g + 4;
int i = x - y - 1; g = g + 4;

इसमें अधिक कदम उठाने पड़ते हैं और कंपाइलर अनुकूलन के लिए अव्यवहार्य कोड में अंतर्दृष्टि की आवश्यकता होती है।

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

यह भी देखें

संदर्भ

  1. John C. Mitchell (2002). प्रोग्रामिंग भाषाओं में अवधारणाएँ. Cambridge University Press. p. 78.
  2. Alfred North Whitehead; Bertrand Russell (1927). गणितीय सिद्धांत. Vol. 1 (2nd ed.). Cambridge University Press. Here: p.665. According to Quine, the term originates from there.


बाहरी संबंध