"The Seasoned Schemer"中的长度函数

Raj*_*hat 5 scheme seasoned-schemer

我一直在阅读The Seasoned Schemer,我遇到了长度函数的这个定义

(define length
  (let ((h (lambda (l) 0)))
    (set! h (L (lambda (arg) (h arg))))
    h))
Run Code Online (Sandbox Code Playgroud)

后来他们说:

(L(lambda(arg)(h arg)))的值是多少?这是功能

(lambda (l)
  (cond ((null? l) 0)
     (else (add1 ((lambda (arg) (h arg)) (cdr l))))))
Run Code Online (Sandbox Code Playgroud)

我不认为我完全理解这一点.我想我们应该将L自己定义为练习.我使用letrec 在长度定义中写了L的定义.这是我写的:

(define length
  (let ((h (lambda (l) 0)))
    (letrec ((L
              (lambda (f)
                (letrec ((LR
                          (lambda (l)
                            (cond ((null? l) 0)
                                  (else
                                   (+ 1 (LR (cdr l))))))))
                  LR))))                  
    (set! h (L (lambda (arg) (h arg))))
    h)))
Run Code Online (Sandbox Code Playgroud)

因此,L将一个函数作为其参数并返回另一个函数,该函数将列表作为其参数并在列表上执行递归.我的解释是正确还是无可救药?无论如何,定义有效

 (length (list 1 2 3 4))  => 4
Run Code Online (Sandbox Code Playgroud)

Ósc*_*pez 3

在《老谋深算》中length最初是这样定义的:

(define length
  (let ((h (lambda (l) 0)))
    (set! h (lambda (l)
              (if (null? l)
                  0
                  (add1 (h (cdr l))))))
    h))
Run Code Online (Sandbox Code Playgroud)

在本书的后面,前面的结果被概括并length根据Y!(应用顺序、命令式 Y 组合器)重新定义,如下所示:

(define Y!
  (lambda (L)
    (let ((h (lambda (l) 0)))
      (set! h (L (lambda (arg) (h arg))))
      h)))

(define L
  (lambda (length)
    (lambda (l)
      (if (null? l)
          0
          (add1 (length (cdr l)))))))

(define length (Y! L))
Run Code Online (Sandbox Code Playgroud)

问题中显示的第一个定义length只是一个中间步骤 -L过程与上面定义的完全相同,您不应该重新定义它。本章这一部分的目的是达到我的答案中所示的第二个定义。