質問

私はClojureの中に無限の怠惰なシーケンスにメタデータを追加しようとすると、私は、スタックオーバーフローを取得し、私は、メタデータを脱いであれば、それだけで正常に動作します。なぜwith-metaマクロは怠惰な配列を破る追加しますか?

まず非常に素晴らしい数の無限の配列を作成します:

(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]

1つのレベルまでのメタデータを移動してみてください。

(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()は怠惰な配列のボディを評価します。あなたのコードは、上記のスタックが爆発するまで、それらすべてを評価し、連続怠惰seqs、上with-metaを呼び出し続けます。私はそれがその本体を評価させることなく、怠惰な配列にメタデータを追加するにはどのような方法が現在ないと思う。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top