2012-02-02 13 views
7

मैं इन प्रक्रियाओं को योजना में सीपीएस फॉर्म में कैसे परिवर्तित करूं?सीपीएस (निरंतरता पासिंग स्टाइल) में कनवर्ट करें

  1. (lambda (x y) 
        ((x x) y)) 
    
  2. (lambda (x) 
        (lambda (f) 
        (f (lambda (y) 
         (((x x) f) y)))) 
    
  3. ((lambda (x) (x x) 
    (lambda (x) (x x)) 
    

* यह किसी भी होमवर्क नहीं है!

उत्तर

22

अध्याय 15 के आसपास से शुरू होने वाले Programming Languages, Application and Interpretation देखें। अध्याय 18 स्वचालित रूप से इसे कैसे करें, इसके बारे में वार्तालाप करता है, लेकिन यदि आप "ऐसा करने के लिए क्या करें" करने वाले फ़ंक्शन को व्यक्त करने के बारे में सोचने से परिचित नहीं हैं, तो आप शायद पहले उंगली अभ्यास का प्रयास करें।

कोई आपके लिए यह नहीं करता है: आप वास्तव में प्रक्रिया को समझना चाहते हैं और योजना से स्वतंत्र रूप से हाथ से ऐसा करने में सक्षम होना चाहते हैं। यह विशेष रूप से असिंक्रोनस जावास्क्रिप्ट वेब प्रोग्रामिंग में आता है, जहां आपके पास वास्तव में परिवर्तन करने के अलावा कोई विकल्प नहीं है।


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

तो अगर हम एक त्रिकोण के hypothenuse गणना करने के लिए एक कार्यक्रम था:

(define (hypo a b) 
    (define (square x) (* x x)) 
    (define (add x y) (+ x y)) 

    (sqrt (add (square a) 
      (square b)))) 

और अगर हम कहते हैं कि केवल आदिम अनुप्रयोगों यहाँ *, +, और sqrt, तो सभी अन्य कार्यशील परिभाषाएँ और फ़ंक्शन कॉल कर रहे हैं अनुवाद किया जाना है इस तरह, की जरूरत है:

(define (hypo/k a b k) 
    (define (square/k x k) 
    (k (* x x))) 

    (define (add/k x y k) 
    (k (+ x y))) 

    (square/k a 
      (lambda (a^2) 
       (square/k b 
         (lambda (b^2) 
         (add/k a^2 b^2 
           (lambda (a^2+b^2) 
            (k (sqrt a^2+b^2))))))))) 

;; a small test of the function. 
(hypo/k 2 3 (lambda (result) (display result) (newline))) 

पिछले अभिव्यक्ति से पता चलता है कि आप "के अंदर से बाहर" की गणना करने के लिए होने अंत, और परिवर्तन व्यापक है कि: सभी lambdas मूल स्रोत कार्यक्रम में एक अतिरिक्त तर्क लेने की आवश्यकता होती है, और सभी गैर-आदिम अनुप्रयोगों को उस तर्क के रूप में "क्या करना है-अगले" सामान की आवश्यकता होती है।

उद्धृत पुस्तक की धारा 17.2 पर नज़र डालें: इसमें यह शामिल है, साथ ही साथ 17.5, जो इस बारे में बात करता है कि आपको स्रोत कार्यक्रम में सभी लैम्ब्स को क्यों छूने की आवश्यकता है, ताकि उच्च-आदेश केस भी काम करता है ।


का एक और उदाहरण के रूप में बदलना, एक उच्च क्रम मामले के लिए आवेदन किया, मान लें कि हम करते हैं:

(define (twice f) 
    (lambda (x) 
    (f (f x)))) 

फिर कुछ इस तरह का अनुवाद है:

(define (twice/k f k1) 
    (k1 (lambda ...))) 

... क्योंकि वह लैम्ब्डा सिर्फ एक मान है जिसे k1 पर पारित किया जा सकता है। लेकिन निश्चित रूप से, अनुवाद लैम्बडा के माध्यम से भी चलाने की जरूरत है।

हमें पहले f पर x के साथ आंतरिक कॉल करना होगा (और याद रखें कि सभी गैर-आदिम फ़ंक्शन अनुप्रयोगों को उचित "पास-टू-डू-पास" पास करने की आवश्यकता है!"):

(define (twice/k f k1) 
    (k1 (lambda (x k2) 
     (f x (lambda (fx-val) 
       ...))))) 

... कि मान ले और च के लिए फिर से इसे लागू ...

(define (twice/k f k1) 
    (k1 (lambda (x k2) 
     (f x (lambda (fx-val) 
       (f fx-val ...)))))) 

... और अंत में k2 है कि मूल्य वापस:

(define (twice/k f k1) 
    (k1 (lambda (x k2) 
     (f x (lambda (fx-val) 
       (f fx-val k2)))))) 

;; test. Essentially, ((twice square) 7) 
(define (square/k x k) (k (* x x))) 
(twice/k square/k 
     (lambda (squaresquare) 
      (squaresquare 7 
         (lambda (seven^4) 
          (display seven^4) 
          (newline))))) 
+0

मुझे खेद है, यह मेरी मदद नहीं कर रहा है। कोशिश करने के लिए वैसे भी धन्यवाद। –

+1

आपको किस हिस्से में परेशानी हो रही है? क्या आप जानते हैं कि एक साधारण फ़ंक्शन को कैसे बदला जाए, जैसे कि (लैम्ब्डा (एक्स) (+ x 1)) सीपीएस शैली में? मदद करने में बहुत मुश्किल है, जहां आप अटक रहे हैं के मानसिक मॉडल के साथ। क्या आपने उद्धृत पुस्तक में उन अध्यायों से गुजर लिया है, या आपके पास समय नहीं है? – dyoo

+1

हां मेरे पास है, और मुझे पता है कि "सरल" प्रक्रियाओं को कैसे बदलें (लैम्ब्डा (एक्स) (+ x 1)), लेकिन क्या होगा यदि 'एक्स' एक प्रक्रिया है? जैसे (लैम्ब्डा (एक्स) (एक्स 1))? मुझे हर उपयोगकर्ता परिभाषित प्रक्रिया को बदलने की ज़रूरत है, है ना? –

0

आपको चुनने की जरूरत है कि आपको किस स्तर की आवश्यकता है/सीपीएस-ट्रांसफॉर्म करना चाहते हैं।

यदि आप निरंतर में (lambda (x y) ((x x) y)) चाहते हैं ऑन-पासिंग (सीपी) शैली, फिर (lambda (k x y) (k ((x x) y))) ठीक करेगी।

यदि आप चाहते हैं कि इसके तर्क सीपी शैली में भी माना जाए, तो आपको थोड़ा और चाहिए।

मान लीजिए पहले कि केवल दूसरा तर्क (y) सी.पी. रूप में है और इस तरह वास्तव में (lambda (k) (k y0)) की तरह कुछ है और इसलिए अपने मूल्य निकालने के लिए कुछ निरंतरता के साथ कॉल किया जाना चाहिए, तो आप की आवश्यकता होगी:

(lambda (k x y) 
    (y (lambda (y0) (k ((x x) y0))))) 

अंत में मान लें कि x और y दोनों सीपी शैली में हैं।

(lambda (k x y) 
    (x (lambda (x0) 
     (x (lambda (x1) 
      (y (lambda (y0) 
       (k ((x0 x1) y0)))))) 

यहाँ आप स्वतंत्रता x और y के लिए कॉल को पुन: व्यवस्थित करने के लिए है: तो फिर तुम जैसे कुछ की आवश्यकता होगी। या शायद आपको केवल x पर एक कॉल की आवश्यकता है, क्योंकि आप जानते हैं कि इसका मान निरंतरता पर निर्भर नहीं है जिसे इसे कहा जाता है। उदाहरण के लिए:

(lambda (k x y) 
    (y (lambda (y0) 
     (x (lambda (x0) 
      (k ((x0 x0) y0)))))) 

आपके द्वारा पूछे जाने वाले अन्य अभिव्यक्तियों को समान रूप से परिवर्तित किया जा सकता है।

संबंधित मुद्दे