Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In clojure, how to build lazy sequence using iterate function

Tags:

clojure

The clojure document gives the following examples:

(take 10 (iterate (partial + 2) 0))

(def powers-of-two (iterate (partial * 2) 1))
(take 10 powers-of-two)

(def fib (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1])))
(take 10 fib)

Anyone can explain the syntax of clojure's iterate function in more detail? I am very confused with all the usage. Why two brackets are there in (fn [[a b]] [b (+ a b)])?

Another example can be found here:

(defn iter [[x y]]
  (vector y (+ x y)))

(nth (iterate iter [0 1]) 10000)
like image 629
lkahtz Avatar asked Dec 21 '11 01:12

lkahtz


People also ask

How do you iterate in Clojure?

One way to translate an imperative for loop to Clojure is to use the for macro. The above function will return all the numbers from 0 to 9 incremented by 1. However, it appears you simply want to iterate over a sequential collection and use each item.

What is a lazy sequence Clojure?

Overview. Clojure is not a lazy language. However, Clojure supports lazily evaluated sequences. This means that sequence elements are not available ahead of time and produced as the result of a computation.

What is lazy sequence?

Lazy sequences are regular sequences where each item is computed on demand rather than up front. For example, consider this array of numbers: let numbers = Array(1... 100000) That will hold 100,000 numbers.


1 Answers

iterate takes a function f and an initial value x and produces a lazy sequence. The first element in the seq is x. Each subsequent element is computed by calling f with the previous element.

Example 1:

(iterate (partial + 2) 0)

This generates a sequence, starting at 0, where each element is the previous element with 2 added to it. I.e.:

0
(+ 2 0) ; => 2
(+ 2 2) ; => 4
(+ 2 4) ; => 6
; etc

Each element in the seq is passed to (partial + 2) when generating the following element.

Example 2:

(iterate (partial * 2) 1)

This generates a sequence, starting at 1, where each element is the previous element multiplied by 2. I.e.:

1
(* 2 1) ; => 2
(* 2 2) ; => 4
(* 2 4) ; => 8
(* 2 8) ; => 16
; etc

Again, you can see how each element feeds into the generation of the next one.

Example 3:

(iterate (fn [[a b]] [b (+ a b)]) [1 1])

Firstly, (fn [[a b]] ...) is a way to destructure a value into parts. In this case, the function accepts a two-element vector and unpacks it into the local variables a and b.

The function returns a two-element vector containing b and the sum of a and b (i.e. the second value in the previous pair and the sum of both values in the previous pair).

With this in mind, this iterate call generates:

[1 1]
[1 (+ 1 1)] ; => [1 2]
[2 (+ 1 2)] ; => [2 3]
[3 (+ 2 3)] ; => [3 5]
[5 (+ 3 5)] ; => [5 8]
; etc

Then (map first ...) grabs the first value in each pair, which gives you your Fibonacci sequence.

like image 147
harto Avatar answered Oct 03 '22 04:10

harto