Question

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])))?

Was it helpful?

Solution

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top