[英]Little Schemer: why wrap (mk-length mk-length) into a function?
在Little Schemer的書的第9章中,在為任意長輸入構建length
函數時,建議以下內容(在第170-171頁上 ),在以下代碼段(來自第168頁本身)中:
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l)))))))
(mk-length mk-length))))
該部分(mk-length mk-length)
永遠不會返回,並且將自身無限地應用於自身:
因為我們只是一次又一次地將
mk-length
應用於自身...
和
但是現在我們已經從函數中提取了
(mk-length mk-length)
來使length
不再返回函數。
現在,要解決這本書,建議:
在最后一個正確的
length
版本中,將mk-length
的應用本身轉換為一個函數。
像這樣:
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(cond
((null? l) 0 )
(else
(add1 (length (cdr l)))))))
(lambda (x)
((mk-length mk-length) x)))))
我不解的是:
如果(mk-length mk-length)
不返回函數
我們如何將(mk-length mk-length)
應用於某事物,就好像它是一個函數一樣?
(lambda (x) ((mk-length mk-length) x))
如何將(mk-length mk-length)
包裝到函數中解決“永不返回”(即無限遞歸)問題? 我的理解是:
(lambda (x) ((mk-length mk-length) x))
x
只會傳遞給永不遞歸的函數,該函數永遠不會返回。
這個電話
(mk-length mk-length)
只會調用一次mk-length
。
如果mk-length
恰巧稱其為self,則將再次評估mk-length
的主體-但是mk-length
並不總是自稱。
關於原因-請注意,您的表達式中沒有函數使用define
命名。 所有函數表達式都使用引入匿名函數的lambda
。
該示例表明,即使僅使用匿名函數,也可以編寫遞歸函數。 該函數不是直接命名該函數(使用define
),而是作為參數傳遞給另一個函數-並且該函數具有其參數的名稱。
您可能復制了錯誤的代碼段,這是您實際談論的代碼段之前的代碼段。 您顯示的第一個代碼完全沒問題。 循環是這樣的:
((lambda (mk-length)
(mk-length mk-length)) ; (1)
(lambda (mk-length)
((lambda (length) ; (2)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))) ; (4)
(mk-length mk-length)))) ; (3)
這已經回答了這里 :應用程序(1)
觸發的應用(2)
觸發的應用(3)
向右走 ,這相當於(1)
因此,循環。
將其包裝為lambda(aka eta-expansion )會延遲應用程序(3)
直到在(4)
對構造的length
進行了調用為止,這是完全可以的(您還復制了一些拼寫錯誤):
((lambda (mk-length)
(mk-length mk-length)) ; (1)
(lambda (mk-length) ; (5)
((lambda (length) ; (2)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))) ; (4)
(lambda (x) ; (3)
(mk-length mk-length) x))))
(3)
現在是lambda表達式,不是應用程序。 評估此lambda表達式會產生一個匿名函數。 此lambda函數將執行該應用程序(mk-length mk-length)
后 ,當length
被調用。
(更詳細的解釋:) (3)
只是立即返回拉姆達函數獲取綁定到length
,和(lambda (l) ...)
正高興地返回,使得當 (lambda (l) ...)
會應用於一些列表中,從而可能導致該length
1到在被稱為(4)
然后才應用(mk-length mk-length)
拉姆達內部(3)
實際上將執行-給人的新(lambda (l) ...)
匿名函數最終將應用到那里的(cdr l)
。
1個 length
是(lambda (x) ((mk-length mk-length) x))
,這意味着(length (cdr l))
與((mk-length mk-length) (cdr l))
mk-length
綁定到整個lambda-expression (5)
),並最終綁定到((lambda (l) ...) (cdr l))
。
尼娜
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.