当我尝试添加元数据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只要您拨打withMetaLazySeq评估其身体。你失去了你的懒惰。

public final class LazySeq extends Obj implements ISeq, List{
    ...
    public Obj withMeta(IPersistentMap meta){
        return new LazySeq(meta, seq());
    }
    ...
}

seq()评估懒惰SEQ的身体,如果它尚未评估。上面的代码中不断连续懒seqs调用with-meta,其评估它们所有,直到堆栈爆炸。我不认为有任何当前的方法来添加元数据到一个懒惰的序列,而不会导致它来评估它的身体。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top