2014-05-15 139 views
2

最近我一直在與計劃混爲一談,並提供了以下代碼示例。瞭解計劃代碼的結果

(define f (lambda (g) (lambda (x) (g (+ (g x) (g x)))))) 
(define e (lambda (x) (* x 3))) 
(define d (f e)) 
(d 4) 

輸出是

=> 72 

如果有人能提供給我的解釋是如何處理這個代碼一步一步,併產生結果的綱要,這將有助於援助與我對語言的掌握。

我的理解是非常基本的,拋棄我的是(d 4),因爲我認爲(最初)(define d (f e))有兩個參數。我一直在閱讀在線鏈接的材料,但似乎無法找到正在尋找的正確解釋。

+0

'(define d(fe))'定義'd'來保存評估結果值(fe)',它調用'f'所指的函數,其值爲作爲論點。 –

回答

2

我打算用substitution model來解釋。這個想法是,你可以用它的定義替換一個變量,並用過程體中的表達式替換一個過程應用程序,並且正式的參數被擴展爲它的參考。例如。:

(define square (lambda (x) (* x x))) 
(square 5) 

所以我們先從(sqrt 5)因爲它開始PROCESSS(而不是定義)

(square 5)    ; ==> subst square 
((lambda (x) (* x x)) 5) ; ==> apply x=5 
(* 5 5)     ; ==> 25 

現在讓我們做同樣的你的例子:

(定義F(拉姆達(克)(拉姆達(X)(克(+(GX)(GX)))))) (定義E(拉姆達(X)(*×3))) (定義d(FE)) (d 4)

或者,我們可以只是因爲它的定義d開始是一個表達式(f e)

(f e) ; subs f ==> 
((lambda (g) (lambda (x) (g (+ (g x) (g x))))) e) ; apply g=e ==> 
(lambda (x) (e (+ (e x) (e x))))     ; subst first e ==> 
(lambda (x) ((lambda (x) (* x 3)) (+ (e x) (e x)))) ; apply x=(+ (e x) (e x)) ==> 
(lambda (x) (* (+ (e x) (e x)) 3))     ; subst e+apply x=x ==> 
(lambda (x) (* (+ (* x 3) (* x 3)) 3))    ; now this is d 

因此,在現實fe現在是無關緊要的,因爲通過替換規則,你可以寫(define d (lambda (x) (* (+ (* x 3) (* x 3)) 3))代替。 然後我們做(d 4)使用它的新定義:

(d 4)          ; subst d ==> 
((lambda (x) (* (+ (* x 3) (* x 3)) 3)) 4) ; apply x=4 ==> 
(* (+ (* 4 3) (* 4 3)) 3)     ; ==> 72 

我在左下角的下拉菜單中手動完成這一點,但你可以簡單的方案代碼通過選擇「中級學生」自動完成它DrRacket的語言並按STEP> |。你的代碼有13個步驟。然而,它可以幫助手動執行幾次手動操作,並在看完SICP videoes之後更好地理解,如果您完成questions in the book,那麼您會很好。圖書和視頻都是免費的,所以你只需要付出你的時間來購買王牌計劃。

+0

最好的解釋,謝謝!我剛剛閱讀了lambda微積分的一些文檔,現在這對我來說非常合適。我開始相信功能語言的力量。 – Algorithm

+0

@Sylwester'sqr',而不是'sqrt'。 –

+0

@ ChrisJester-Young OMG你是對的。我想要一個比視頻更簡單的例子(平方和),並認爲「square」很不錯,並稱之爲「sqrt」。更新!謝謝 :-) – Sylwester

0

爲了

(d 4) 

工作,d必須是一個過程。由於d使用

(define d (f e)) 

定義,那麼

(f e) 

必須返回一個過程。方式f已被定義,其返回值的確是一個lambda表達式。

(f e) 

返回值是

(lambda (x) (e (+ (e x) (e x)))) 

如果你替換什麼e代表,您可以:

(lambda (x) (* (+ (* x 3) (* x 3)) 3)) 

因此,

(define d (f e)) 

可以轉換爲

(define d (lambda (x) (* (+ (* x 3) (* x 3)) 3))) 

現在,

(d 4) 

可以翻譯成

(* (+ (* 4 3) (* 4 3)) 3) 

計算結果爲72

+0

在'(lambda(x)(*(+(* x 3)(* x 3))3))'部分,爲什麼操作符只將'e'和'x 3'替換爲'x' ? – Algorithm

+0

@Algorithm由於'e'被定義爲'(lambda(* x 3))',我們可以用'(e x)'替代'(* x 3)'。希望回答你的問題。 –

+0

啊,我想我到了那裏。我仍然在嘗試熟悉語法。 '(e x)'是一個過程調用'e'的參數是否是'x'? – Algorithm

1

你的程序就相當於

(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x))))))) 
    (let ((e (lambda (x) (* x 3)))) 
    (let ((d (f e))) 
     (d 4))))  

一般情況下,應letrec一直在使用,不let,但在這裏它沒有什麼區別。 letrec允許程序在其主體內引用其自己的名稱,即,遞歸let不允許這樣的參考。例如,定義f的lambda表達式不包含對f的任何引用。

現在通過試圖找出d的值來進行評估,將其用作值爲4的參數調用的函數。因此執行應用程序(f e)。一般而言,應用程序((lambda (x) ...) v)被減小(let ((x v)) ...):返回

(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x))))))) 
    (let ((e (lambda (x) (* x 3)))) 
    (let ((d (let ((g e))   ; <--- 
       (lambda (x) (g (+ (g x) (g x))))) 
      )) 
     (d 4)))) 

的封閉:

(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x))))))) 
    (let ((e (lambda (x) (* x 3)))) 
      (let ((g e)) 
     (let ((d (lambda (x) (g (+ (g x) (g x)))))) 
     (d 4)))))  ; <--- 

現在d的值被發現是一個程序,從而執行該應用程序(d 4)

(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x))))))) 
    (let ((e (lambda (x) (* x 3)))) 
    (let ((g e)) 
     (let ((d (lambda (x) (g (+ (g x) (g x)))))) 
     (let ((x 4)) 
      (g (+ (g x) (g x)))))))) ; <--- 

(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x))))))) 
    (let ((e (lambda (x) (* x 3)))) 
    (let ((g e)) 
     (let ((d (lambda (x) (g (+ (g x) (g x)))))) 
     (let ((x 4)) 
      (let ((temp1 (+ (g x) (g x)))) ; <--- 
      (g temp1))))))) 

這就是

...... 
     (let ((x 4)) 
      (let ((temp2 (g x))    ; <--- 
       (temp3 (g x)))    
      (let ((temp1 (+ temp2 temp3))) 
       (g temp1))))))))   

...... 
     (let ((x 4)) 
      (let ((temp2 ((lambda (x1) (* x1 3)) x)) ; <--- 
       (temp3 (g x)))    
      (let ((temp1 (+ temp2 temp3))) 
       (g temp1))))))))    

...... 
     (let ((x 4)) 
      (let ((temp2 (let (x1 x) (* x1 3)))  ; <--- 
       (temp3 (g x)))    
      (let ((temp1 (+ temp2 temp3))) 
       (g temp1))))))))    

...... 
     (let ((x 4)) 
      (let ((temp2 (let (x1 4) (* x1 3)))  ; <--- 
       (temp3 (g x)))    
      (let ((temp1 (+ temp2 temp3))) 
       (g temp1))))))))    

...... 
     (let ((x 4)) 
      (let ((temp2    (* 4 3))  ; <--- 
       (temp3 (g x)))    
      (let ((temp1 (+ temp2 temp3))) 
       (g temp1))))))))    

等。這不是計劃實際運作的方式,而是接近。最後,我們到達

...... 
     (let ((x 4)) 
      (let ((temp2 12) 
       (temp3 12))    
      (let ((temp1 24)) 
       (g temp1))))))))    ; <--- 

...... 
      (let ((temp1 24)) 
       ((lambda (x2) (* x2 3)) temp1))))))  ; <--- 

...... 
       (let (x2 24) (* x2 3))))))  ; <--- 

...... 
       (* 24 3) ))))  ; <--- 

...... 
       72 ))))   ; []