怠惰なシーケンスにメタデータを追加します
-
20-08-2019 - |
質問
私は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
はできるだけ早くあなたがwithMeta
にLazySeq
を呼び出すと、その本体を評価しますので。あなたの怠惰を失うます。
public final class LazySeq extends Obj implements ISeq, List{
...
public Obj withMeta(IPersistentMap meta){
return new LazySeq(meta, seq());
}
...
}
それはまだ評価されていない場合は、 seq()
は怠惰な配列のボディを評価します。あなたのコードは、上記のスタックが爆発するまで、それらすべてを評価し、連続怠惰seqs、上with-meta
を呼び出し続けます。私はそれがその本体を評価させることなく、怠惰な配列にメタデータを追加するにはどのような方法が現在ないと思う。
所属していません StackOverflow