簡體   English   中英

Little Schemer:為什么將(mk-length mk-length)包裝為一個函數?

[英]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)))))

我不解的是:

  1. 如果(mk-length mk-length)

    不返回函數

    我們如何將(mk-length mk-length)應用於某事物,就好像它是一個函數一樣?

     (lambda (x) ((mk-length mk-length) x)) 
  2. 如何將(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM