在除数函数中使用let

时间:2018-03-28 20:31:34

标签: 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:谢谢,我不知道它被称为名为 let 。我正在查找let,我找到了let*,但他们没有将其命名为let

1 个答案:

答案 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))

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

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