Art*_*ldt 3 lisp clojure lazy-sequences
当我尝试在Clojure中向无限延迟序列添加元数据时,我得到了堆栈溢出,如果我取消元数据,那么它可以正常工作.为什么添加with-meta宏打破了懒惰的seq?
首先创建一个非常好的数字的无限序列:
(defn good []
(lazy-seq
(cons 42
(good))))
user> (take 5 (good))
(42 42 42 42 42)
然后,为每个lazy-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());
}
...
}
Run Code Online (Sandbox Code Playgroud)
seq()如果尚未评估懒惰seq的主体,则对其进行评估.上面的代码不断调用with-meta连续的lazy seqs,它们会一直评估它们,直到堆栈爆炸.我认为目前没有任何方法可以将元数据添加到惰性seq而不会导致它评估其正文.