(take 2 (for [x (range 10)
:let [_ (println x)]
:when (even? x)] x))
>> (* 0
* 1
* 2
* 3
* 4
* 5
* 6
* 7
* 8
* 9
0 2)
我以为我只是太笨了。但事实并非如此,事实证明 Clojure 实际上会计算任何惰性序列(如果可用)的前 32 个元素。哎哟。
我在 :let
中有一个带有递归调用的 for
。我很好奇为什么计算似乎是以广度优先而不是深度优先的方式进行的。当我不断沿着递归树的所有上部分支向下移动时,计算(尽管公平地说,不是内存)似乎呈爆炸式增长。 Clojure 的 32 分块强制进行广度优先评估,尽管代码的逻辑意图是深度优先。
无论如何,有什么简单的方法可以强制惰性序列进行 1 block 而不是 32 block 吗?
最佳答案
迈克尔·福格斯 has written a blog entry on disabling this behavior by providing a custom ISeq implementation .
无耻地窃取the modified version by Colin Jones :
(defn seq1 [#^clojure.lang.ISeq s]
(reify clojure.lang.ISeq
(first [_] (.first s))
(more [_] (seq1 (.more s)))
(next [_] (let [sn (.next s)] (and sn (seq1 sn))))
(seq [_] (let [ss (.seq s)] (and ss (seq1 ss))))
(count [_] (.count s))
(cons [_ o] (.cons s o))
(empty [_] (.empty s))
(equiv [_ o] (.equiv s o))))
给出了更简单的方法in The Joy of Clojure :
(defn seq1 [s]
(lazy-seq
(when-let [[x] (seq s)]
(cons x (seq1 (rest s))))))
关于clojure - 'for' 在 clojure 中实际上不是懒惰的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10556421/