scheme - let 在除数函数中的使用

标签 scheme racket

    (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))

因此,为了回答您的问题,最初的i2。然后递归调用将i增加到3,依此类推,方式与上面的代码相同。与所有调用一样,绑定(bind)变量对于调用来说是本地的,因此每一轮都有自己的i

现在,如果您查看此版本以及名为 let 的版本,您会注意到 let 中的参数和绑定(bind)更加紧密,因此其意图代码更容易理解。此外,当您知道命名的 let 允许您使用新绑定(bind)调用同一 block 时,您会认为命名的 let 比替代方案更容易阅读。

关于scheme - let 在除数函数中的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49543657/

相关文章:

syntax - 将空列表传递给定义类型 : possible?

scheme - Racket (方案)错误: expected the name of the symbol after the quote,但找到了零件

lambda - 使用 lambda 的方案

scheme - 如果有的话,Scheme 中 letrec 的这个定义有什么问题?

scheme - 在使用 DrScheme 的 SICP 练习 2.26 中,为什么 cons 返回一个列表,而不是一对列表?

lisp - 在满足谓词之前构建列表的替代方法?

scheme - 在Scheme中,什么时候理性谓词会产生假?

swift - 方案 : possible in Swift? 中可爱的 lambda 技巧

scheme - Dr. Racket 中 Scheme 的元循环求值器

scheme - 如何在 DrScheme 中重新定义常量标识符?