Lisp 向延迟序列添加元数据
当我试图在Clojure中将元数据添加到一个无限的惰性序列时,我会得到一个堆栈溢出,如果我去掉元数据,那么它就可以正常工作。为什么用meta添加Lisp 向延迟序列添加元数据,lisp,clojure,lazy-sequences,Lisp,Clojure,Lazy Sequences,当我试图在Clojure中将元数据添加到一个无限的惰性序列时,我会得到一个堆栈溢出,如果我去掉元数据,那么它就可以正常工作。为什么用meta添加宏会破坏惰性seq 首先创建一个非常好的数字的无限序列: (defn good [] (lazy-seq (cons 42 (good)))) user> (take 5 (good)) (42 42 42 42 42) (定义良好[] (续) (反对意见42) (好) 用户>(取5(好)) (42 42 42 42 42)
宏会破坏惰性seq
首先创建一个非常好的数字的无限序列:
(defn good []
(lazy-seq
(cons 42
(good))))
user> (take 5 (good))
(42 42 42 42 42)
(定义良好[]
(续)
(反对意见42)
(好)
用户>(取5(好))
(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]
(定义错误[]
(续)
(反对意见42)
(带meta)
(坏)
{:padding(4})))
用户>(取5(坏))
java.lang.StackOverflowerr(无源文件:0)
[抛出类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也不好[]
(带meta)
(续)
(反对意见42)
(也不好)
{:填充4})
用户>(取5(foo))
java.lang.StackOverflowerr(无源文件:0)
[抛出类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>
(defn也起作用[]
(续)
(缺点4)
(带meta)
()
{(a:5})))
用户>(也适用)
(4)
用户>(元(rest(也工作)))
{:a 5}
用户>
因为只要您在LazySeq
上调用withMeta
,一个LazySeq
就会评估它的主体。你失去了你的懒惰
public final class LazySeq extends Obj implements ISeq, List{
...
public Obj withMeta(IPersistentMap meta){
return new LazySeq(meta, seq());
}
...
}
seq()。上面的代码在连续的惰性seq上使用meta
不断调用,这将对它们进行求值,直到堆栈爆炸为止。我认为目前没有任何方法可以向惰性seq添加元数据,而不让它评估其主体。惰性seq和with meta都是宏,因此您应该能够进一步了解macroexpand resp。macroexpand-1.FWIW,中的第二个补丁,如果被接受,将提供一种方法。