簡體   English   中英

在Clojure中使用遞歸生成惰性seq?

[英]Generate lazy seq with recursion in Clojure?

我是clojure的新手,目前正在努力使用loop / recur 問題基本上就是為什么我的'自定義' range功能。 不返回懶惰序列。 我的實現有什么問題,或者你不應該在這種情況下使用遞歸嗎?

(defn my-range
  [nr]
  (loop [l nr acc '()]
    (if (< l 1)
      acc
      (recur (dec l) (conj acc l)))))

當我運行它:

> (time (take 10 (my-range 100000))) ;; "Elapsed time: 85.443 msecs"
> (time (take 10 (range 100000))) ;; "Elapsed time: 0.095 msecs"

非常大的時差使我相信列表首先構建然后10。

你不在my-range使用任何惰性結構。 由於您從最后開始組裝列表並朝着開頭方向工作,因此訪問前十個元素的唯一方法是首先實現所有其他元素。

懶惰的序列從頭開始,一直到最后,如下所示:

(defn my-range
  ([end]
   (my-range 1 end))
  ([start end]
   (when (<= start end)
     (lazy-seq (cons start (my-range (inc' start) end))))))

這里的訣竅是你沒有返回一個已實現的序列。 而是返回一個存儲此函數的對象:

#(cons start (my-range (inc' start) end))

當有人在該對象上調用seq時,它將調用上述函數,緩存其結果並返回該結果。 seq未來調用將只返回緩存的結果。 但請注意,傳遞給cons的第二個參數也是一個惰性序列(因為對my-range的調用會返回一個lazy-seq ),因此反過來,它只會在必要時實現。

為了完整起見,編寫此函數的另一種方法如下:

(defn my-range
  [end]
  (take end (iterate inc' 1)))

這工作,因為iterate ,並take兩回懶序列。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM