3

当我尝试将元数据添加到 Clojure 中的无限惰性序列时,我得到了堆栈溢出,如果我删除元数据,那么它就可以正常工作。为什么添加with-meta宏会破坏惰性序列?

首先创建一个非常好的数字的无限序列:

(定义好 []
  (惰性序列
    (缺点 42
      (好的))))

用户>(取5(好))
(42 42 42 42 42)

然后,为每个惰性序列实例添加一些元数据:

(定义不好 []
  (惰性序列
    (缺点 42
      (带元
       (坏的)
       {:padding 4}))))


用户>(取5(坏))
java.lang.StackOverflowError (NO_SOURCE_FILE:0)
  [抛出类 clojure.lang.Compiler$CompilerException]

尝试将元数据上移一级:

(定义也不好 []
  (带元
   (惰性序列
     (缺点 42
       (也很糟糕)))
   {:填充 4}))

用户>(取 5 (foo))
java.lang.StackOverflowError (NO_SOURCE_FILE:0)
  [抛出类 clojure.lang.Compiler$CompilerException]

以下是有限序列上的元数据示例:

(定义也有效 []
     (惰性序列
       (缺点 4
         (带元
          ()
          {:a 5}))))

用户>(也有效)
(4)
user> (meta (rest (also-works)))
{:a 5}
用户>
4

1 回答 1

6

因为LazySeq一旦你调用 a ,它就会评估它的withMeta身体LazySeq。你会失去你的懒惰。

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

seq()如果尚未评估惰性序列的主体,则评估它。您上面的代码不断调用with-meta连续的惰性序列,它会评估它们,直到堆栈爆炸。我认为目前没有任何方法可以将元数据添加到惰性序列而不导致它评估其主体。

于 2009-06-29T01:52:31.047 回答