1

所以我试图理解这段代码,在盯着它看了太久之后,我决定在这里问是否有人可以帮助我理解它是如何以及为什么工作的

(define knock-knock
 (letrec ([dig (lambda (i)
                 (cons (* i (list-ref knock-knock (- i 1)))
                       (dig (+ i 1))))])
   (cons 1 (dig 1))))

然后按名称调用该函数,其值为:

(list-ref knock-knock 5)

所以我的主要问题是我看不到letrec结束的地方。另一件事是我没有得到一个列表,那么我应该在第 3 行引用的列表中的第 4 个元素是什么?

4

1 回答 1

2

首先,请注意:这不是正常的 Scheme,因为它需要惰性评估。

在惰性求值中,仅在需要时才计算值。所以,为了定义knock-knock,我们可以做

(cons 1 <thunk: (dig 1)>)

即,我们生成一对,但我们不需要第二个元素,因此我们将其评估推迟到以后。

当我们真正想要评估第二个元素时,我们已经knock-knock定义了,所以我们可以引用它。

下一个元素是通过取前一个 ( i-1-st) 元素来计算的,并将其乘以i. 所以这将生成序列 {n!}: 1,1,2,6,24,...

将此代码直接翻译为(通常是惰性的)Haskell 语言如下所示:

knock :: [Int]
knock = 1 : dig 1
    where dig i = (i * knock !! (i-1)) : dig (i+1)
于 2015-07-29T15:14:49.727 回答