(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:谢谢,我不知道它被称为namedlet
。我在查找 let
时发现了 let*
,但它们并没有名为 let
。
最佳答案
作为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
,依此类推,方式与上面的代码相同。与所有调用一样,绑定(bind)变量对于调用来说是本地的,因此每一轮都有自己的i
。
现在,如果您查看此版本以及名为 let
的版本,您会注意到 let
中的参数和绑定(bind)更加紧密,因此其意图代码更容易理解。此外,当您知道命名的 let
允许您使用新绑定(bind)调用同一 block 时,您会认为命名的 let
比替代方案更容易阅读。
关于scheme - let 在除数函数中的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49543657/