Вопрос

I'm trying to understand the execution of the following code:

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

This is what I would expect the execution to look like

[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 .... 

Which is obviously incorrect, since the result is wrong. The only execution I could come up with that produced the correct result is this:

[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 ....

Is this a correct "representation" of the state of head and tail during the execution? If so, why does (rest fibs) return a single item? Is it because of a recursive call like (rest (rest (rest [1 1 2 3])))?

Это было полезно?

Решение

Fibs is (0 1 ...) (because of the (concat [0 1] ... ) at the beginning). (rest fibs) is (1 ...). Then (map + fibs (rest fibs)) is

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

So fibs is (0 1 1 ...). Since we got the next item, we can calculate yet another one:

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

And it goes on...

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

Think of fibs as if it was already there, and the state of (map + fibs (rest fibs) as moving on the list of the fibs that already exist (that's fine because it ends up calculating everything we need on the way).

It could also help to just write down the two sequences:

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

(I'd draw arrows here to indicate what we already got and where the result goes, but I can't do that here so well).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top