14

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

Y = λx.(λv.(x x) v) 

कौन सा वास्तविक एक से भी कम है:

Y = λf.(λx.f (x x)) (λx.f (x x)) 

और, मेरे आश्चर्य के लिए, काम किया। कुछ उदाहरण:

// JavaScript 
Y = function(x){ 
    return function(v){ 
    return x(x, v); 
    }; 
}; 
sum = Y(function(f, n){ 
    return n == 0 ? 0 : n + f(f, n - 1); 
}); 
sum(4); 

; Scheme 
(define Y (lambda (x) (lambda (v) (x x v)))) 
(define sum (Y 
    (lambda (f n) 
     (if (equal? n 0) 
      0 
      (+ n (f f (- n 1))))))) 
(sum 4) 

दोनों स्निपेट आउटपुट 10 (0 से 4 तक सारांश) अपेक्षित के रूप में।

यह क्या है, यह छोटा क्यों है और हम लंबे संस्करण को क्यों पसंद करते हैं?

+0

उह, यह कम है, क्योंकि यह किसी अन्य भाषा में है होना चाहिए? मैं योजना में धाराप्रवाह नहीं हूं, लेकिन ऐसा लगता है कि जेएस और योजना परिभाषा बराबर हैं। आपका सवाल वास्तव में क्या है? "हम सभी सबसे छोटी भाषा में क्यों नहीं लिख रहे हैं?" – lanzz

+0

मैं अब भी आपके हिस्से का मतलब नहीं हूं। क्या आपका मतलब जेएस भाग है क्योंकि आपने लाइनब्रेक्स या स्कीम भाग जोड़ा है क्योंकि आपने सभी लाइन ब्रेक छोड़े हैं? यह सवाल कोई समझ नहीं आता है। – Sebastian

+0

@lanzz क्या आप वाई-कॉम्बिनेटर जानते हैं? यह दोनों भाषाओं में प्रदान किए गए उदाहरण से बड़ा है। मैंने उन्हें पोस्ट किया ताकि इसे अधिक लोगों द्वारा समझा जा सके। अगर यही कारण है कि आप नीचे आ गए हैं तो कृपया पुनर्विचार करें, आप गलत हैं। – MaiaVictor

उत्तर

13

कारण यह छोटा है कि आपने जो लागू किया है वह वाई संयोजन नहीं है। यह कुछ ऐसा है जो वास्तविक वाई संयोजक के बीच है, और ऐसा कुछ जिसे कभी-कभी यू संयोजक के रूप में जाना जाता है। एक उचित Y Combinator हो, यह काम करना चाहिए:

(define sum 
    (Y (lambda (f) 
     (lambda (v) (if (equal? n 0) 0 (+ n (f (- n 1)))))))) 

या जावास्क्रिप्ट में:

sum = Y(function(f) { return function(n) { 
    return n == 0 ? 0 : n + f(n-1); 
};}); 

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

+0

ग्रेट उत्तर, धन्यवाद!हम यू-संयोजक पर वाई-संयोजक क्यों पसंद करते हैं, यद्यपि? संपादित करें: ओह, रुको, मेरा यू-कॉम्बिनेटर नहीं है, जो अभी भी आसान है। क्या इस के लिए कोई नाम है? – MaiaVictor

+1

@ डॉककट: वास्तविक संस्करण का मुख्य बिंदु यह है कि कोड नहीं बदलता है - आपको यह जानने की आवश्यकता नहीं है कि आप एक रिकर्सिव कॉल कर रहे हैं या किसी अन्य फ़ंक्शन को कॉल कर रहे हैं। (साथ ही, मुझे नहीं पता कि आपके संस्करण के लिए कोई नाम है या नहीं।) –

+0

@ विकलिब आपके लैम्ब्डा कैल्क को 'λx' के लिए सरलीकृत किया जा सकता है। (एक्स एक्स) 'जो * यू * संयोजक है। हालांकि, इसे लागू करने और इसका उपयोग करने के लिए (जावास्क्रिप्ट में) जिस तरह से आपने यहां किया है, आपको '(x x)' '(λv। ... v) 'में लपेटकर तत्काल रिकर्सन को रोकने की आवश्यकता है, इस प्रकार:' λx। λv। (एक्स एक्स) v'। ऐसा इसलिए है क्योंकि जावास्क्रिप्ट आवेदक आदेश मूल्यांकन का उपयोग करता है और लैम्ब्डा कैल्क सामान्य क्रम का उपयोग करता है। आश्चर्य की बात नहीं है, वाई-संयोजक यू-संयोजक का उपयोग करके और भी आसानी से व्यक्त किया जाता है। 'वाई: = (यू (λf। Λx.f (x x))) 'जो' (λf। Λx.f (x x)) (λf। Λx.f (x x)) तक विस्तारित है। – naomik

4

"वास्तविक" संस्करण से अंतर यह है कि आपको अपने स्वयं के फ़ंक्शन को पैरामीटर के साथ पास करने की आवश्यकता होती है, जिसे आप आमतौर पर करने की आवश्यकता नहीं रखते हैं - वाई आपके कार्य को अपने आप को रिकर्सिस संस्करण देकर उस पर सार करता है । जावास्क्रिप्ट में

योग सिर्फ

Y (function(rec){ return function (n) { return n==0 ? 0 : n + rec(n-1); };}) 

मैं Y Combinator समझा जब मैं पुनर्गठित common JS expression

function Y (f) { 
    function alt (x) { 
     function rec (y) { // this function is basically equal to Y (f) 
      return x(x)(y); // as x === alt 
     } 
     return f (rec); 
    } 
    return alt(alt); 
} 
+0

ग्रेट स्पष्टीकरण, "वाई आपके कार्य को अपने आप को रिकर्सिस संस्करण देकर उस पर सार करता है।" भाग ने इसे बहुत स्पष्ट बना दिया। धन्यवाद! – MaiaVictor

+0

जो मुझे लंबे समय तक समझ में नहीं आया था वह था कि दो 'alt' फ़ंक्शंस मूल रूप से वही थे और एक-दूसरे को वैकल्पिक रूप से कॉल करते थे। – Bergi

+0

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