序列

LazySeq是刚接触Clojure的人比较容易弄不清楚的一个东西。比如你们觉得下面这个代码的输出是什么？

``````(map #(println %) [1 2 3])
``````

`dorun``doall` 函数迫使一个LazySeq里面的函数被调用。 `doseq` 宏, 我们在 "迭代" 那一节提到过的, 会迫使一个或者多个LazySeq里面的函数调用。 `for` 宏, 也在是"迭代”那一节提到的，不会强制调用LazySeq里面的方法， 相反， 他会返回另外一个LazySeq。

``````(dorun (map #(println %) [1 2 3]))
(doseq [i [1 2 3]] (println i))
``````

``````(doseq [item [1 2 3]] (println item)) ; -> nil
(dorun (map #(println %) [1 2 3])) ; -> nil
(doall (map #(do (println %) %) [1 2 3])) ; -> (1 2 3)
``````

LazySeq使得创建无限序列成为可能。因为只有需要使用的数据才会在用到的时候被调用创建。比如

``````(defn f
"square the argument and divide by 2"
[x]
(println "calculating f of" x)
(/ (* x x) 2.0))

; Create an infinite sequence of results from the function f
; for the values 0 through infinity.
; Note that the head of this sequence is being held in the binding "f-seq".
; This will cause the values of all evaluated items to be cached.
(def f-seq (map f (iterate inc 0)))

; Force evaluation of the first item in the infinite sequence, (f 0).
(println "first is" (first f-seq)) ; -> 0.0

; Force evaluation of the first three items in the infinite sequence.
; Since the (f 0) has already been evaluated,
; only (f 1) and (f 2) will be evaluated.
(doall (take 3 f-seq))

(println (nth f-seq 2)) ; uses cached result -> 2.0
``````

``````(defn f-seq [] (map f (iterate inc 0)))
(println (first (f-seq))) ; evaluates (f 0), but doesn't cache result
(println (nth (f-seq) 2)) ; evaluates (f 0), (f 1) and (f 2)
``````

``````(defn consumer [seq]
; Since seq is a local binding, the evaluated items in it
; are cached while in this function and then garbage collected.
(println (first seq)) ; evaluates (f 0)
(println (nth seq 2))) ; evaluates (f 1) and (f 2)

(consumer (map f (iterate inc 0)))
``````