Reputation: 4180
Came across this interesting implementation of Fibonacci generator in clojure. Bit difficult to understand the self-reference part. Any help on mental modelling this would be very useful.
(def fib-seq
(lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))
Upvotes: 1
Views: 365
Reputation: 10484
Macroexpanding (lazy-cat [0 1] (map + (rest fib-seq) fib-seq)
leads to:
(concat (lazy-seq [0 1]) (lazy-seq (map + (rest fib-seq) fib-seq)))
(map + coll1 coll2)
returns a new collection where the first item of the first list is added to the first item of the second list, the second item of the first list is added to the second item of the second list, and so on.
user> (map + [1 2 3 4] [1 2 3 4])
(2 4 6 8)
So we start with 0 and 1, and then we get the first of the rest of the fib-seq
(1) to the first element of the fib-seq
(0), this leads to 1. Then we get the next element of the fib-seq
again, which is the 1
we just realized and add it to the second item of the fib-seq
(1), which leads to 2, and so on.
So we lazily concat [0 1] to the result of summing the two collections after it shifted by 1:
[0 1] <+ concat>
[1 + 0
1 + 1
2 + 1
3 + 2
...]
user> (take 10 fib-seq)
(0 1 1 2 3 5 8 13 21 34)
Hope this helps.
Upvotes: 4