2012-03-29 29 views
9

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

उत्तर

12

आप call/cc, as described here का उपयोग कर एक वाई संयोजक को कार्यान्वित कर सकते हैं। - एक स्पष्ट स्वयं आवेदन के बिना Y Combinator

उपप्रमेय call/cc के माध्यम से 1. Y Combinator: (इस स्वच्छ पद उल्लेख के लिए जॉन कोवान बहुत धन्यवाद) उस पोस्ट का हवाला देते हुए, यहाँ ओलेग के कार्यान्वयन है।

(define (Y f) 
    ((lambda (u) (u (lambda (x) (lambda (n) ((f (u x)) n))))) 
    (call/cc (call/cc (lambda (x) x))))) 

यहाँ, हम एक तथ्य यह है कि

((lambda (u) (u p)) (call/cc call/cc)) 

और

((lambda (u) (u p)) (lambda (x) (x x))) 

observationally बराबर हैं प्रयोग किया जाता है।

+1

कमाल, ठीक वही है जो मैं चाहता हूं। बहुत बहुत धन्यवाद। – day

+0

@ वाबेरी मैंने उस कोड स्निपेट को उद्धृत करने का एक तरीका खोजने का निर्णय लिया है जो उम्मीद है कि "उचित उपयोग" - अनुकूल है। –

+0

बहुत अच्छा, धन्यवाद। – wberry

6

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

#lang racket 

(define (factorial f n) 
    (if (= n 0) 1 (* n (f f (- n 1))))) 

(factorial factorial 3) 

यह धोखाधड़ी की तरह लग सकता है, लेकिन यह वाई संयोजक की नींव है। शायद आप उन प्रतिबंधों के सेट को कस कर सकते हैं जिनके बारे में आप सोच रहे हैं?

पीएस .: अगर यह होमवर्क है, तो कृपया मुझे उद्धृत करें!

+0

ठीक है, मैं पहले से ही इस चाल को रिकर्सन करने के लिए जानता हूं। मुझे आश्चर्य है कि यदि कॉल/सीसी का उपयोग करने वाला एक गैर-आत्म-संदर्भ तरीका एक पुनरावर्ती कार्य को परिभाषित करने के लिए मौजूद है, तो अपने 'फैक्टोरियल' कहें। यह होमवर्क व्यायाम नहीं है! धन्यवाद। – day

+1

@plmday जॉन का समाधान पहले से ही आत्म-संदर्भ नहीं है। आपको कॉल/सीसी' से और क्या चाहिए? –

+0

@ सैमोबिन-होचस्टेड वैसे, यह है, 'एफ' खुद को संदर्भित करता है, है ना?मैं देखना चाहता हूं कि हम 'कॉल/सीसी' के साथ कितनी दूर जा सकते हैं, विशेष रूप से, इसकी क्षमता दी गई है, क्या हम इसे रिकर्सिव फ़ंक्शन को परिभाषित करने के सामान्य या असामान्य तरीके को अनुकरण करने के लिए नियोजित कर सकते हैं। – day

2

मुझे डर है call/cc वास्तव में इसके साथ बहुत कुछ नहीं करना है। रिकर्सिव फ़ंक्शन को परिभाषित करने के केवल दो तरीके हैं:

  • मान लीजिए कि आपकी भाषा रिकर्सिव फ़ंक्शन परिभाषाओं को अनुमति देती है; यानी, एक फ़ंक्शन बॉडी संलग्न कार्य को संदर्भित कर सकता है, या फ़ंक्शन f का फ़ंक्शन g फ़ंक्शन का संदर्भ ले सकता है जिसका शरीर f को संदर्भित करता है। इस मामले में, ठीक है, आप इसे सामान्य तरीके से लिखते हैं।
  • यदि आपकी भाषा इन दोनों को मना करती है, लेकिन इसमें अभी भी प्रथम श्रेणी के फ़ंक्शन और लैम्बडा हैं, तो आप वाई संयोजनकर्ता की तरह fixed-point combinator का उपयोग कर सकते हैं। आप अपना फ़ंक्शन लिखते हैं ताकि यह एक अतिरिक्त तर्क के रूप में लिया जा सके जो रिकर्सिव चरण का प्रतिनिधित्व करने के लिए है; हर जगह जहां आप रिकर्स करेंगे, इसके बजाय आप उस तर्क का आह्वान करेंगे।

तो factorial के लिए, आप इसे इस प्रकार लिख:

(define (factorial-step recurse n) 
    (if (zero? n) 
     1 
     (* n (recurse (- n 1))))) 

Y Combinator का जादू है कि यह निर्माण करती recurse समारोह है कि factorial-step को खिलाया जा होता है।