在clojure中,如何使用迭代函数构建延迟序列

时间:2011-12-21 01:41:38

标签: clojure

clojure document给出了以下示例:

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

任何人都可以更详细地解释clojure的迭代函数的语法?我对所有用法都非常困惑。为什么有两个括号(fn [[a b]] [b(+ a b)])?

可以找到另一个例子here

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

(nth (iterate iter [0 1]) 10000)

1 个答案:

答案 0 :(得分:15)

iterate获取函数f和初始值x并生成一个惰性序列。 seq中的第一个元素是x。通过使用前一个元素调用f来计算每个后续元素。

示例1:

(iterate (partial + 2) 0)

这将生成一个序列,从0开始,其中每个元素都是前一个元素,并添加了2。即:

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

生成以下元素时,seq中的每个元素都会传递给(partial + 2)

示例2:

(iterate (partial * 2) 1)

这会生成一个序列,从1开始,其中每个元素都是前一个元素乘以2. I.e。:

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

同样,您可以看到每个元素如何输入下一个元素的生成。

示例3:

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

首先,(fn [[a b]] ...)是将destructure值转换为部分的方法。在这种情况下,函数接受一个双元素向量并将其解包为局部变量ab

该函数返回一个包含bab之和的双元素向量(即前一对中的第二个值和前一个值的总和)对)。

考虑到这一点,此iterate调用会生成:

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

然后(map first ...)抓取每对中的第一个值,这将为您提供斐波纳契数列。