macro - Clojure懶惰序列使用



clojure map (1)

我無法理解如何在Clojure中創建一個懶惰的序列。

宏的文檔對我來說一點也不清楚:

用法:(lazy-seq&body)獲取一個返回ISeq或nil的表達式體,並生成一個Seqable對象,該對象僅在第一次調用seq時調用body,並將緩存結果並在隨後的所有內容中返回seq電話。

我見過的所有例子似乎都是這樣的:

; return everything in the sequence starting at idx n
(defn myseq-after-n [n]
  (...)
)

(def my-lazy-seq
  (lazy-seq (conj [init-value] (myseq-after-n 2)))
)

所以,我沒有得到的第一件事是,因為lazy-seq不在調用conj之外,它是如何阻止conj在評估時生成無限序列的?

我的第二個問題是,懶惰的序列定義總是採用這種一般形式嗎?

https://code.i-harness.com


lazy-seq調用只是在第一次訪問時執行主體,然後緩存並在將來再次調用時返回相同的結果。

如果要使用它來構建長(甚至無限)序列,則需要在返回的序列中遞歸嵌套其他lazy-seq調用。 這是我能想到的最簡單的案例:

(defn ints-from [n]
  (cons n (lazy-seq (ints-from (inc n)))))

(take 10 (ints-from 7))
=> (7 8 9 10 11 12 13 14 15 16)

任何(ints-from n)調用都會產生一個以n開頭的序列,然後是一個惰性序列(ints-from(inc n))。 這是一個無限的列表,但這不是問題,因為lazy-seq確保(int-from(inc n))僅在需要時被調用。 您可以在沒有lazy-seq的情況下嘗試完全相同的代碼,並且您很快就會得到Error。

lazy-seq只是創建延遲序列的眾多可能方法之一,而且通常不是最方便的。 以下是創建延遲序列的一些其他有趣/有用的方法:

; range is an easy way to get an infinite lazy sequence of integers, starting with zero     
(take 10 (range))
=> (0 1 2 3 4 5 6 7 8 9)

; map produces lazy sequences, so the following is lazy 
(take 10 (map #(* % %) (range)))
=> (0 1 4 9 16 25 36 49 64 81)

; iterate is a good way of making infinite sequenes of the form x, f(x), f(f(x))..... 
(take 10 (iterate (partial * 2) 1))
=> (1 2 4 8 16 32 64 128 256 512)




lazy-evaluation