6

我试图了解以下代码的执行:

(def fibs 
  (concat (lazy-seq [0 1]) (lazy-seq (map + fibs (rest fibs)))))

这就是我希望执行的样子

[0 1 : (map + [0 1] [1]) => 1
[0 1 1 : (map + [0 1 1] [1 1]) => 1 2
[0 1 1 1 2 : (map + [0 1 1 2] [1 1 2]) => 1 2 3
[0 1 1 1 2 1 2 3 : (map + [0 1 1 2 3] [1 1 2 3]) => 1 2 3 5
[0 1 1 1 2 1 2 3 1 2 3 5 .... 

这显然是不正确的,因为结果是错误的。我能想到的唯一产生正确结果的执行是:

[0 1 : (map + [0 1] [1]) => 1
[0 1 1 : (map + [1 1] [1]) => 2
[0 1 1 2 : (map + [1 2] [2]) => 3
[0 1 1 2 3 : (map + [2 3] [3]) => 5
[0 1 1 2 3 5 ....

这是执行过程中头部和尾部状态的正确“表示”吗?如果是这样,为什么(rest fibs)返回单个项目?是因为像 (rest (rest (rest [1 1 2 3]))) 这样的递归调用吗?

4

1 回答 1

6

Fibs 是(0 1 ...)(因为(concat [0 1] ... )在开头)。(rest fibs)(1 ...)。然后(map + fibs (rest fibs))

((+ 0 1) ...) => (1 ...)

所以fibs是(0 1 1 ...)。由于我们得到了下一项,我们可以计算另一个:

(1 (+ 1 1) ...) => (1 2 ...)

它继续...

(1 2 (+ 1 2) ...)

将 fibs 想象成它已经存在,并且将状态(map + fibs (rest fibs)视为在已经存在的 fibs 列表上移动(这很好,因为它最终会计算出我们在途中需要的所有内容)。

写下这两个序列也可能会有所帮助:

 (0 1 1 2 3 5 ...)
+(1 1 2 3 5 ...)
=(1 2 3 5 8 ...)

(我会在这里画箭头来指示我们已经得到了什么以及结果的去向,但我不能在这里做得那么好)。

于 2012-11-16T21:53:17.400 回答