将元数据添加到惰性序列
当我尝试将元数据添加到 Clojure 中的无限惰性序列时,出现堆栈溢出,如果我删除元数据,那么它就可以正常工作。 为什么添加 with-meta
宏会破坏惰性序列?
首先创建一个非常好的数字的无限序列:
(defn good [] (lazy-seq (cons 42 (good)))) user> (take 5 (good)) (42 42 42 42 42)
然后,向每个惰性序列实例添加一些元数据:
(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>
When I try to add metadata to an infinite lazy sequence in Clojure, I get a stack overflow, and if I take off the metadata, then it works just fine. Why does adding the with-meta
macro break the lazy seq?
First create an infinite seq of a very nice number:
(defn good [] (lazy-seq (cons 42 (good)))) user> (take 5 (good)) (42 42 42 42 42)
Then, add some metadata to each of the lazy-seq instances:
(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]
Try moving the meta data up one level:
(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]
Here is an example of meta data on a finite sequence:
(defn also-works [] (lazy-seq (cons 4 (with-meta () {:a 5})))) user> (also-works) (4) user> (meta (rest (also-works))) {:a 5} user>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因为一旦您在
LazySeq
上调用withMeta
,LazySeq
就会评估其主体。 你失去了你的懒惰。seq()
会评估惰性 seq 的主体(如果尚未评估)。 上面的代码不断在连续的惰性序列上调用with-meta
,这会评估它们直到堆栈爆炸。 我认为目前没有任何方法可以将元数据添加到惰性序列而不使其评估其主体。Because a
LazySeq
evaluates its body as soon as you callwithMeta
on theLazySeq
. You lose your laziness.seq()
evaluates the lazy seq's body if it hasn't already been evaluated. Your code above keeps callingwith-meta
on successive lazy seqs, which evaluates them all until the stack explodes. I don't think there's currently any way to add metadata to a lazy seq without causing it to evaluate its body.