题
当我尝试添加元数据Clojure中的无限慵懒的序列中,我得到一个堆栈溢出,如果我脱掉的元数据,然后它工作得很好。为什么添加with-meta
宏打破懒惰SEQ?
首先创建一个非常好的数无限SEQ:
(defn good [] (lazy-seq (cons 42 (good)))) user> (take 5 (good)) (42 42 42 42 42)
然后,添加一些元数据到每个懒惰-SEQ实例:
(defn bad [] (lazy-seq (cons 42 (with-meta (bad) {:padding 4})))) user> (take 5 (bad)) java.lang.StackOverflowError (NO_SOURCE_FILE:0) [Thrown class clojure.lang.Compiler$CompilerException]
尝试移动元数据上一层:
(defn also-bad [] (with-meta (lazy-seq (cons 42 (also-bad))) {:padding 4})) user> (take 5 (foo)) java.lang.StackOverflowError (NO_SOURCE_FILE:0) [Thrown class clojure.lang.Compiler$CompilerException]
下面是元数据的一个有限序列的示例:
(defn also-works [] (lazy-seq (cons 4 (with-meta () {:a 5})))) user> (also-works) (4) user> (meta (rest (also-works))) {:a 5} user>
解决方案
由于一个LazySeq
只要您拨打withMeta
在LazySeq
评估其身体。你失去了你的懒惰。
public final class LazySeq extends Obj implements ISeq, List{
...
public Obj withMeta(IPersistentMap meta){
return new LazySeq(meta, seq());
}
...
}
seq()
评估懒惰SEQ的身体,如果它尚未评估。上面的代码中不断连续懒seqs调用with-meta
,其评估它们所有,直到堆栈爆炸。我不认为有任何当前的方法来添加元数据到一个懒惰的序列,而不会导致它来评估它的身体。
不隶属于 StackOverflow