2014-02-14 27 views
13

我剛剛開始覺得我對使用lambda在球拍和方案中的使用有一個模糊的理解,當我遇到下面的'cons'和'car'的替代定義SICP在SICP中使用lambda作爲cons/car/cdr的定義

(define (cons x y) 
    (lambda (m) (m x y))) 

(define (car z) 
    (z (lambda (p q) p))) 

(define (cdr z) 
    (z (lambda (p q) q))) 

對於我的生活,我只是無法解析它們。

任何人都可以解釋如何解析或擴展這些對於新手來說是有意義的嗎?

+1

您可能會感興趣[如何設置!在方案中定義?](http://stackoverflow.com/q/16733472/1281433)其中接受的答案顯示如何實現存儲一個值的單元格。這是同樣的想法。另請參閱[Lambda微積分CONS對與Lisp一起實現](http://stackoverflow.com/q/13537622/1281433),其定義與您的一樣:'pair≡λx.λy.λz.zx y'。 –

回答

21

這是一種表達數據的有趣方式:作爲函數。注意cons的這個 的定義返回lambda,其中關閉參數xy,在其中捕獲它們的值。還要注意的是,返回的拉姆達 接收功能m作爲參數:

;creates a closure that "remembers' 2 values 
(define (cons x y) (lambda (m) (m x y))) 
;recieves a cons holding 2 values, returning the 0th value 
(define (car z)  (z (lambda (p q) p))) 
;recieves a cons holding 2 values, returning the 1st value 
(define (cdr z)  (z (lambda (p q) q))) 

在上面的代碼z是一個閉合,這是由cons創建的相同,並且在 的過程的主體,我們'再傳遞另一個lambda作爲參數, 記得m?就是這樣!它期望的功能。

瞭解以上情況,很容易看出carcdr是如何工作的;讓我們 解剖如何carcdr被解釋評估一個步驟在一個時間:

; lets say we started with a closure `cons`, passed in to `car` 
(car (cons 1 2)) 

; the definition of `cons` is substituted in to `(cons 1 2)` resulting in: 
(car (lambda (m) (m 1 2))) 

; substitute `car` with its definition 
((lambda (m) (m 1 2)) (lambda (p q) p)) 

; replace `m` with the passed parameter 
((lambda (p q) p) 1 2) 

; bind 1 to `p` and 2 to `q`, return p 
1 

總結:cons創建一個閉合一個可以「記住的兩個值,car 接收封閉件,並將它傳遞函數充當選擇器,用於 零值,並作爲第一個值選擇cdr行爲,關鍵 這裏要明白的是,lambda充當 closure。 散熱效果如何呢?我們只需要的功能是存儲並檢索任意數據!

在大多數LISP中嵌套組合物car & cdrdefined up to 4 deep。例如:

(define caddr (lambda (x) (car (cdr (cdr x))))) 
+0

謝謝。我想我明白了(但它會讓我的大腦受傷)。這要複雜得多,他們描述的其他替代版本的形式:(define(cons xy) (define(dispatch m) (cond((= m 0)x) ((= m 1)y)) ) dispatch) (define(car z)(z 0))看起來我需要理解閉包 - 感謝他們的參考。 – Penguino

+1

另一種選擇在概念上更復雜。它需要條件,比較,功能和功能應用程序 - 而這種替代方法只需要功能和功能應用程序。 –

+0

也許因爲我對函數式語言還不熟悉,第二個看起來對我來說更簡單。在我看來,在'調度'的選擇中,cons在產生正確的輸出時會產生一個潛在的功能,當被問得很好時 - 這看起來很簡單。但是在'lambda'替代缺點中,會產生一種幻像,它只能通過汽車「啓動」才能形成。 – Penguino

2

這應該是很容易與combinatory符號來理解(隱式轉換方案爲討好的功能,f x y = z ==> (define f (λ (x) (λ (y) z)))):

cons x y m = m x y 
car z = z _K   ; _K p q = p 
cdr z = z (_K _I)  ; _I x = x  _K _I p q = _I q = q 

所以我們得到

car (cons x y) = cons x y _K  = _K x y = x 
cdr (cons x y) = cons x y (_K _I) = _K _I x y = _I y = y 

所以定義做我們所期望的。 Easy

在英文中,cons x y值是一個函數,它說「如果你給我一個兩個參數的函數,我會用我持有的兩個參數來調用它,讓它決定如何處理它們,然後!」

換句話說,它需要一個「continuation」函數,並用其(「pair」)創建中使用的兩個參數來調用它。

1

在我看來,明確的訣竅是從年底到年初閱讀的定義,因爲在他們三個人的自由變量總是那些能夠在lambda主體(m內找到,pq)。這裏是開始嘗試翻譯的代碼爲英語,從終端(右下角)(左上角):

(define (cons x y) 
    (lambda (m) (m x y)) 

無論m是,我們懷疑這是因爲它的功能出現在(的旁邊,它必須適用於xy兩者:這是cons的定義xy

(define (car z) 
    (z (lambda (p q) q))) 

無論pq是,當施加一種叫z,和z是值得接受的功能作爲其輸入,則pq第一個是選自:這是定義的car

對於「接受函數作爲輸入的東西」的例子,我們只需要回顧cons的定義。因此,這意味着car接受cons作爲其輸入。

(car (cons 1 2)) ; looks indeed familiar and reassuring 
(car (cons 1 (cons 2 '()))) ; is equivalent 
(car '(1 2)) ; is also equivalent 
(car z) 
; if the previous two are equivalent, then z := '(1 2) 

最後一行的意思是:列表是「接受函數作爲其輸入的東西」。

不要讓你的頭在那一刻旋轉!無論如何,該列表只接受可以在列表元素上工作的函數。這正是因爲我們重新定義了cons的方式。

我認爲這次練習的主要觀點是「計算將操作和數據結合在一起,並且無論您將它們放在一起的順序如何」。

+0

我把賞金拿來獎勵當前的答案,但是我得等24小時因爲理由。 – GlassGhost

+0

@GlassGhost:我希望答案對其他人有用,然後:) – logc