2009-06-28 11 views
3

Wenn ich versuche, Metadaten zu einer unendlichen Lazy-Sequenz in Clojure hinzuzufügen, bekomme ich einen Stack-Überlauf, und wenn ich die Metadaten entferne, funktioniert es gut. Warum bricht das Hinzufügen des with-meta Makros die Lazy Seq?Hinzufügen von Metadaten zu einer Lazy-Sequenz

Zuerst eine unendliche seq von einer sehr schönen Nummer schaffen:

 
(defn good [] 
    (lazy-seq 
    (cons 42 
     (good)))) 

user> (take 5 (good)) 
(42 42 42 42 42) 

Dann einige Metadaten zu jedem der lazy-Seq-Instanzen hinzufügen:

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

Versuchen Sie, die Meta-Daten auf ein bewegtes Ebene:

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

Hier ist ein Beispiel von Meta-Daten auf einer endlichen Folge:

 
(defn also-works [] 
    (lazy-seq 
     (cons 4 
     (with-meta 
     () 
      {:a 5})))) 

user> (also-works) 
(4) 
user> (meta (rest (also-works))) 
{:a 5} 
user> 
+0

Lazy-Seq und With-Meta sind Makros, also sollten Sie mit Makroexpand bzw. Makroexpand-1. – Svante

Antwort

6

Da ein LazySeq so schnell seinen Körper auswertet, wie Sie withMeta auf der LazySeq nennen. Du verlierst deine Faulheit.

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

seq() wertet den Körper des faulen f, wenn es nicht bereits ausgewertet worden ist. Ihr Code oben ruft with-meta auf aufeinanderfolgenden Lazy Seqs auf, die sie alle auswertet, bis der Stapel explodiert. Ich glaube nicht, dass es derzeit eine Möglichkeit gibt, Metadaten zu einem Lazy Seq hinzuzufügen, ohne dass es seinen Körper auswertet.

+0

FWIW, der zweite Patch in [CLJ-1800] (https://dev.clojure.org/jira/browse/CLJ-1800), würde, falls akzeptiert, einen Weg bieten. –

Verwandte Themen