2009-10-29 51 views
83

試圖用Clojure以下,期待有類非延遲序列返回:我如何偷懶序列轉換爲非懶惰Clojure中

(.getClass (doall (take 3 (repeatedly rand)))) 

然而,這仍然返回clojure.lang.LazySeq。我的猜測是doall確實評估整個序列,但返回原始序列,因爲它仍然用於記憶。

那麼從懶惰創建非惰性序列的慣用方法是什麼?

+0

我很驚訝沒有人問你爲什麼要關注'doall'的返回值的實際類型 – tar 2017-11-01 17:14:57

+0

你可以轉換成矢量:'(vec(take 3(repeated rand)))' – Kris 2018-01-23 12:33:50

回答

139

doall是你所需要的。僅僅因爲seq有類型LazySeq並不意味着它有待評估。懶惰的seqs緩存他們的結果,所以你所需要做的只是一次走懶惰seq(就像doall一樣),以強制所有這些,從而使其不會懶惰。 seq確實不是強制對整個集合進行評估。

+2

I'已經將其改爲已接受的答案。在相關說明中,通過什麼方法可以確定LazySeq是否先前已經過評估? – 2009-10-29 14:16:31

+10

我相信你只是叫'實現?'。 – toofarsideways 2012-02-01 02:40:14

+1

可能應該有一個「實現」操作來匹配'實現?'。 – 2017-02-01 14:07:28

4
(.getClass (into '() (take 3 (repeatedly rand)))) 
+3

這是一個可怕的想法。它反轉輸入序列。 – amalloy 2011-08-16 17:52:27

+3

當然,在這種情況下,反轉輸入沒有區別,因爲它們只是3個隨機數.... :-) – mikera 2013-01-03 00:24:37

57

這在某種程度上是一個分類問題。 懶惰序列只是一種類型的序列,因爲它是一個列表,向量或映射。因此,答案當然是「這取決於你想要得到什麼類型的非懶序列:

  • 的前懶(完全評估)懶惰序列(doall ...)
  • 列表:
    從任你選順序訪問(apply list (my-lazy-seq)) OR (into() ...)
  • 供以後隨機訪問的載體(vec (my-lazy-seq))
  • 地圖或者如果你有一些特殊用途的集合。

您可以擁有最適合您需要的任何類型的序列。

+0

這是最好的答案。 – 2014-07-25 16:20:17

+3

接受的答案在技術上是正確的,但是這個答案對我來說最有用。我試圖在vector上映射一個函數,然後將結果吐在一個文件中,甚至在調用doall之後,文件中包含「[email protected]」而不是序列的內容。在返回的值映射上調用vec讓我得到了我需要吐出的文件。 – 2015-11-23 23:17:29

+1

@JesseRosalia很高興知道所有SO中唯一的Rich Hickey響應在技術上是正確的。 ;-) – 2016-03-15 21:02:44

18

這個有錢人似乎知道他的clojure,是絕對正確的。
Buth我覺得這個代碼片段,使用你的榜樣,可能是一個有益的補充這樣一個問題:

=> (realized? (take 3 (repeatedly rand))) 
false 
=> (realized? (doall (take 3 (repeatedly rand)))) 
true 

事實上並沒有改變,但實現已經

+2

但是,值得注意的是,你不需要強制'實現'的整個序列返回'true'。例如。 '(讓[r(range)r?(real?r)](doall(take 1 r))[r?(real?r)])=> [false true]' – 2014-04-21 17:45:13

+15

這位有錢人:D haha​​ – nimrod 2014-08-26 04:40:28

+7

@ nimrod :)然而,雙關語意味着在「h's clojure」。 – Peter 2014-11-04 08:31:17

6

我這個迷迷糊糊這個blog關於doall的帖子不是遞歸的。爲此,我發現在帖子中的第一條評論做了訣竅。沿着線的東西:

(use 'closure.walk) 
(postwalk identity nested-lazy-thing) 

我發現這個有用的單元測試,我想強制的map一些嵌套應用評估,以迫使一個錯誤條件。