在Scheme中遇到问题

时间:2015-07-29 14:58:35

标签: scheme evaluation evaluation-strategy

所以我试图理解这段代码,在长时间盯着它之后我决定问这里是否有人可以帮助我理解它是如何工作的原因

(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个元素是什么?

1 个答案:

答案 0 :(得分: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)