(define divisors (lambda (n) (let f ((i 2)) (cond ((>= i n) '()) ((integer? (/ n i)) (cons i (f (+ i 1)))) (else (f (+ i 1)))))))
我对(let f ((i 2)).....)
部分以及使用(f (+ i 1))
的递归调用感到有些困惑。
f
是否全部成为((i 2))
?以及(f (+ i 1))
部分如何正常工作?我认为(+ i 1)
变为3
,但接下来会发生什么?
编辑:我不太清楚let
是如何运作的。我不太确定如何说出我不理解的内容。如果有人能够解释let
如何与递归调用一起工作,那将会有所帮助。我已经看过let
的其他例子,但我真的不明白它在这种方法中是如何运作的。
edit2:谢谢,我不知道它被称为名为 let
。我正在查找let
,我找到了let*
,但他们没有将其命名为let
。
答案 0 :(得分:3)
作为let
第一部分的符号称为let
。您可能知道标准let
:
(let ((i 2))
body ...)
只是立即调用的匿名函数的缩写:
((lambda (i)
body ...)
2)
使用名为let
的名称,您可以为该函数指定一个名称,这样您就可以将其作为一个函数从身体中调用。除了影子较少外,它相当于:
(define (divisors n)
(define (f i)
(cond
((>= i n) '())
((integer? (/ n i))
(cons i (f (+ i 1))))
(else (f (+ i 1)))))
(f 2))
为了回答您的问题,最初的i
是2
。然后,递归调用将i
增加到3
,依此类推,与上面的代码相同。与所有调用一样,绑定变量是调用的本地变量,因此每一轮都有自己的i
。
现在,如果您查看此版本以及名为let
的版本,您会注意到let
中的参数和绑定更加接近,因此代码的意图更容易理解。此外,当您知道命名let
允许您使用新绑定调用相同的块时,您会认为命名的let
比替代方法更容易阅读。