अधिकांश भाषाओं में बाइंडिंग एक मूल विशेषता क्यों नहीं है?


11

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

लेकिन आईएमएचओ ने इसे एक देशी विशेषता के रूप में लागू करना निम्नलिखित कोड को बदलने के रूप में सरल था-

int a,b,sum;
sum := a + b;
a = 10;
b = 20;
a++;

इसके लिए-

int a,b,sum;
a = 10;
sum = a + b;
b = 20;
sum = a + b;
a++;
sum = a + b;

मतलब हर निर्देश के बाद बाध्यकारी निर्देश को असाइनमेंट के रूप में रखना, किसी भी चर के सही मान में अभिव्यक्ति में निहित है। इसके बाद, अनावश्यक निर्देशों (या संकलन के बाद विधानसभा में अनुकूलन) को ट्रिम करना होगा।

तो, क्यों यह ज्यादातर भाषाओं में मूल रूप से समर्थित नहीं है। विशेष रूप से भाषाओं के सी-परिवार में?

अपडेट करें:

अलग-अलग राय से, मुझे लगता है कि मुझे इस प्रस्तावित "बाध्यकारी" को अधिक सटीक रूप से परिभाषित करना चाहिए-

  • यह एक तरह से बाध्यकारी है। केवल योग एक + बी से जुड़ा हुआ है, न कि इसके विपरीत।
  • बंधन का दायरा स्थानीय है।
  • एक बार बंधन स्थापित हो जाने के बाद, इसे बदला नहीं जा सकता है। मतलब, एक बार राशि + बी से बंधी हो, तो राशि हमेशा एक + बी होगी।

उम्मीद है कि विचार अब स्पष्ट है।

अपडेट 2:

मुझे बस यह P # सुविधा चाहिए थी । आशा है कि यह भविष्य में भी रहेगा।


14
संभवतः क्योंकि किसी भी कंपाइलर डेवलपर ने इस सुविधा को C में जोड़ने की कोशिश की है, उसे नीचे गिराकर गोली मार दी गई है।
पेट विल्सन

मैं वन-वे (दाएं से बाएं) बंधन के बारे में बात कर रहा हूं, दो-तरफा नहीं। बंधन हमेशा केवल एक चर को प्रभावित करेगा।
गुलशन

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

11
यह "सबसे" प्रोग्रामिंग भाषाओं की एक विशेषता नहीं हो सकता है, लेकिन यह है की एक विशेषता सबसे लोकप्रिय प्रोग्रामिंग भाषा: Excel।
डब्ल्यू पर Jörg W Mittag

2
अभिव्यक्ति पेड़ों के लिए धन्यवाद, यह पहले से ही सी # में संभव है। मैंने कल इसके बारे में ब्लॉग किया: happyynomad121.blogspot.com/2013/01/…
HappyNomad

जवाबों:


9

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

आपको यह विचार करना होगा कि यह हमेशा वह नहीं है जो आप चाहते हैं। इतने सारे लोग विशेष रूप से छोरों में बनाए गए बंदों द्वारा काटे जाते हैं क्योंकि बंद करने वाले चर रखते हैं, न कि किसी बिंदु पर इसके मूल्य की एक प्रति, यानी for (i = 0; i < 10; i++) { var f = function() { return i; }; /* store f */ }दस क्लोजर बनाता है जो वापस आते हैं 9। तो आपको दोनों तरीकों का समर्थन करने की आवश्यकता होगी - जिसका अर्थ है "जटिलता बजट" पर दो बार लागत और फिर भी एक अन्य ऑपरेटर। संभवतः यह कोड का उपयोग करने और कोड का उपयोग न करने के बीच भी अक्षमता है, जब तक कि प्रकार प्रणाली पर्याप्त परिष्कृत नहीं होती है (अधिक जटिलता)।

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

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


मुझे लगता है कि आपके पास 3 अंक हैं- 1) यह अनिवार्य नहीं है स्टाइल प्रोग्रामिंग। इन दिनों अधिकांश भाषाएं कुछ प्रतिमानों तक ही सीमित नहीं हैं। मुझे नहीं लगता कि यह इस प्रतिमान शैली से बाहर है एक अच्छा तर्क है। 2) जटिलता। आपने कई और जटिल चीजें दिखाई हैं जो पहले से ही समर्थित हैं। यह एक क्यों नहीं? मुझे पता है कि लगभग कोई उपयोग नहीं करने वाले ऑपरेटरों का समर्थन किया जा रहा है। और यह एक पूरी तरह से नई सुविधा है। तो संगतता मुद्दा कैसे हो सकता है। मैं किसी चीज को बदल या मिटा नहीं रहा हूं। 3) हार्ड कार्यान्वयन। मुझे लगता है कि वर्तमान दिन के संकलक में पहले से ही इसे अनुकूलित करने की क्षमता है।
गुलशन

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

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

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

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

3

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


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

इससे कोई फर्क नहीं पड़ता। हर बार जब आप को लिखने aया b, आप हर एक जगह है कि पर इसके प्रभाव पर विचार करने की जरूरत है sumप्रयोग किया जाता है, और हर जगह आप पढ़ सकते हैं कि sumआप पर विचार करने के क्या जरूरत है aऔर bकर रहे हैं। गैर-तुच्छ मामलों के लिए, यह जटिल हो सकता है, खासकर अगर वास्तविक अभिव्यक्ति के लिए बाध्य sumरनटाइम में बदल सकता है।
jprete

मैं नियम की सिफारिश करूंगा कि एक बार बाध्यकारी होने के बाद बाध्यकारी अभिव्यक्ति को बदला नहीं जा सकता है। यहां तक ​​कि असाइनमेंट भी असंभव होगा। यह एक अभिव्यक्ति की तरह एक बार अर्ध-स्थिर जैसा होगा। इसका मतलब है, एक बार राशि + बी के लिए बाध्य है, यह हमेशा बाकी कार्यक्रम के दौरान एक + बी होगा।
गुलशन

3

हां 'पता है, मैं इस पागल लग रहा है कि प्रतिक्रियाशील प्रोग्रामिंग एक Web2.0 वातावरण में शांत हो सकता है। क्यों लग रहा है? खैर, मेरे पास यह एक पृष्ठ है जो ज्यादातर एक तालिका है जो हर समय तालिका-सेल ऑनक्लिक घटनाओं के जवाब में बदलता है। और सेल क्लिक्स का मतलब अक्सर एक कॉल या पंक्ति में सभी कोशिकाओं के वर्ग को बदलना है; और इसका मतलब है कि अन्य संबंधित कोशिकाओं को खोजने के लिए getRefToDiv () और इसी तरह के अंतहीन लूप।

IOW, जावास्क्रिप्ट के ~ 3000 लाइनों में से कई मैंने लिखा है कि वस्तुओं को खोजने के अलावा कुछ भी नहीं है। हो सकता है कि प्रतिक्रियाशील प्रोग्रामिंग कम लागत पर वह सब कर सके; और कोड की लाइनों में भारी कमी पर।

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


3

मुझे लगता है कि आप जो वर्णन कर रहे हैं उसे स्प्रेडशीट कहा जाता है:

A1=5
B1=A1+1
A1=6

... फिर B1रिटर्न 7 का मूल्यांकन ।

संपादित करें

सी भाषा को कभी-कभी "पोर्टेबल असेंबली" कहा जाता है। यह एक अनिवार्य भाषा है, जबकि स्प्रेडशीट, आदि, घोषणात्मक भाषाएं हैं। जब आप बदलते हैं तो पुनर्मूल्यांकन की B1=A1+1उम्मीद B1करना और कहना A1निश्चित रूप से घोषणात्मक है। घोषणात्मक भाषाएं (जिनमें से कार्यात्मक भाषाएं एक सबसेट हैं) को आमतौर पर उच्च स्तरीय भाषा माना जाता है, क्योंकि वे हार्डवेयर कैसे काम करती हैं, इससे दूर हैं।

संबंधित नोट पर, सीढ़ी तर्क जैसी स्वचालन भाषाएं आमतौर पर घोषणात्मक होती हैं। यदि आप तर्क की एक पंक्ति लिखते हैं, जो कहती है कि output A = input B OR input Cवह उस कथन का लगातार मूल्यांकन करने जा रही है, और Aजब भी Bया Cबदल सकती है। फ़ंक्शन स्वचालन आरेख जैसी अन्य स्वचालन भाषाएं (यदि आप सिमुलिंक का उपयोग कर चुके हैं तो आप इससे परिचित हो सकते हैं) भी घोषणात्मक हैं, और लगातार निष्पादित होते हैं।

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

A = B || C;

... और चूंकि यह हर समय निष्पादित होता है, इसलिए यह घोषणात्मक हो जाता है। Aलगातार मूल्यांकन किया जाएगा।


3

C, C ++, Objective-C:

ब्लॉक बाध्यकारी सुविधा प्रदान करते हैं जिसे आप खोज रहे हैं।

आपके उदाहरण में:

योग: = ए + बी;

आप एक संदर्भ में sumअभिव्यक्ति के लिए सेट कर रहे हैं a + bजहाँ aऔर bमौजूदा चर रहे हैं। आप बिल्कुल ऐसा कर सकते हैं कि "ब्लॉक" (उर्फ क्लोजर, उर्फ ​​लंब्डा एक्सप्रेशन) के साथ C, C ++, या ऑब्जेक्टिव-सी के साथ Apple के एक्सटेंशन (PDF):

__block int a = 0, b = 0;           // declare a and b
int (^sum)(void);                   // declare sum
sum = ^(void){return a + b;};       // sum := a + b

यह sumउस ब्लॉक पर सेट होता है जो a और b का योग लौटाता है। __blockभंडारण वर्ग विनिर्देशक इंगित करता है कि aऔर bबदल सकते हैं। उपरोक्त को देखते हुए, हम निम्नलिखित कोड चला सकते हैं:

printf("a=%d\t b=%d\t sum=%d\n", a, b, sum());
a = 10;
printf("a=%d\t b=%d\t sum=%d\n", a, b, sum());
b = 32;
printf("a=%d\t b=%d\t sum=%d\n", a, b, sum());
a++;
printf("a=%d\t b=%d\t sum=%d\n", a, b, sum());

और उत्पादन प्राप्त करें:

a=0      b=0     sum=0
a=10     b=0     sum=10
a=10     b=32    sum=42
a=11     b=32    sum=43

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


2

सी ++

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

#include <iostream>

template <class R, class A, class B>
class Binding {
public:
    typedef R (*BinOp)(A, B);
    Binding (A &x, B &y, BinOp op)
        : op(op)
        , rx(x)
        , ry(y)
        , useCache(false)
    {}
    R value () const {
        if (useCache && x == rx && y == ry) {
            return cache;
        }
        x = rx;
        y = ry;
        cache = op(x, y);
        useCache = true;
        return cache;
    }
    operator R () const {
        return value();
    }
private:
    BinOp op;
    A &rx;
    B &ry;
    mutable A x;
    mutable B y;
    mutable R cache;
    mutable bool useCache;
};

int add (int x, int y) {
    return x + y;
}

int main () {
    int x = 1;
    int y = 2;
    Binding<int, int, int> z(x, y, add);
    x += 55;
    y *= x;
    std::cout << (int)z;
    return 0;
}

हालांकि यह सवाल का जवाब नहीं देता है, मुझे आपके द्वारा प्रस्तुत विचार पसंद है। क्या अधिक सामान्य संस्करण हो सकता है?
गुलशन

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