2009-05-28 3 views
7

Ich habe gerade angefangen mit Clojure zu spielen und das erste, was ich dachte, versuche ich speichern und abrufen eine Liste von Strukturen, wie in Suart Halloway Beispiel here.Clojure: slurping Strukturen aus Datei fehlschlägt mit String-Attributen mit Leerzeichen

Mein Spieß/schlürft einen Hash von Strukturen mit gut funktioniert, wenn ich struct Instanzen ohne Leerzeichen in den Attribut-Strings wie folgt verwendet werden:

(struct customer "Apple" "InfiniteLoop") 

Aber wenn ich diese:

(struct customer "Apple" "Infinite Loop 1") 

ich erhalte eine Fehlermeldung:

Exception in thread "main" clojure.lang.LispReader$ReaderException: java.lang.ArrayIndexOutOfBoundsException: 7 (test-storing.clj:19) 
    at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2719) 
    at clojure.lang.Compiler$DefExpr.eval(Compiler.java:298) 
    at clojure.lang.Compiler.eval(Compiler.java:4537) 
    at clojure.lang.Compiler.load(Compiler.java:4857) 
    at clojure.lang.Compiler.loadFile(Compiler.java:4824) 
    at clojure.main$load_script__5833.invoke(main.clj:206) 
    at clojure.main$init_opt__5836.invoke(main.clj:211) 
    at clojure.main$initialize__5846.invoke(main.clj:239) 
    at clojure.main$null_opt__5868.invoke(main.clj:264) 
    at clojure.main$legacy_script__5883.invoke(main.clj:295) 
    at clojure.lang.Var.invoke(Var.java:346) 
    at clojure.main.legacy_script(main.java:34) 
    at clojure.lang.Script.main(Script.java:20) 
Caused by: clojure.lang.LispReader$ReaderException: java.lang.ArrayIndexOutOfBoundsException: 7 
    at clojure.lang.LispReader.read(LispReader.java:180) 
    at clojure.core$read__4168.invoke(core.clj:2083) 
    at clojure.core$read__4168.invoke(core.clj:2081) 
    at clojure.core$read__4168.invoke(core.clj:2079) 
    at clojure.core$read__4168.invoke(core.clj:2077) 
    at chap_03$load_db__54.invoke(chap_03.clj:71) 
    at clojure.lang.AFn.applyToHelper(AFn.java:173) 
    at clojure.lang.AFn.applyTo(AFn.java:164) 
    at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2714) 
    ... 12 more 
Caused by: java.lang.ArrayIndexOutOfBoundsException: 7 
    at clojure.lang.PersistentArrayMap$Seq.first(PersistentArrayMap.java:216) 
    at clojure.lang.APersistentMap.hashCode(APersistentMap.java:101) 
    at clojure.lang.Util.hash(Util.java:55) 
    at clojure.lang.PersistentHashMap.entryAt(PersistentHashMap.java:134) 
    at clojure.lang.PersistentHashMap.containsKey(PersistentHashMap.java:130) 
    at clojure.lang.APersistentSet.contains(APersistentSet.java:33) 
    at clojure.lang.PersistentHashSet.cons(PersistentHashSet.java:59) 
    at clojure.lang.PersistentHashSet.create(PersistentHashSet.java:34) 
    at clojure.lang.LispReader$SetReader.invoke(LispReader.java:974) 
    at clojure.lang.LispReader$DispatchReader.invoke(LispReader.java:540) 
    at clojure.lang.LispReader.read(LispReader.java:145) 
    ... 20 more 

Je nach der Menge der Felder in der Struktur, ich könnte Außerdem erhalten Sie nur einen Teil der Zeichenfolge als Attributnamen anstelle des Fehlers. Zum Beispiel: Loop 1

Ich benutze eine Speicher-Funktion wie folgt aus:

(defn store-customer-db [customer-db filename] 
    (spit filename (with-out-str (print customer-db)))) 

und eine Lese-Funktion wie folgt aus:

(defn load-db [filename] 
    (with-in-str (slurp filename)(read))) 

Von der Ausgabedatei Spucke kann ich sehen, dass Der Druck gibt keine doppelten Anführungszeichen an die Saiten, was ein Problem beim Schlürfen zu sein scheint. Was wäre die richtige Lösung dafür?

Meine Clojure-Version ist 1.0, und der Beitrag ist ein paar Wochen alt Schnappschuss.

+0

In #clojure (irc) erhalten Sie wahrscheinlich autoritative und sofortige Antworten. – alphazero

Antwort

10

print und println sind für menschenlesbare Ausgabe gedacht. Wenn Sie etwas drucken möchten, das später erneut eingelesen werden soll, verwenden Sie pr oder prn.

user> (read-string (with-out-str (prn {"Apple" "Infinite Loop"}))) 
{"Apple" "Infinite Loop"} 

Während:

user> (read-string (with-out-str (print {"Apple" "Infinite Loop"}))) 
java.lang.ArrayIndexOutOfBoundsException: 3 (NO_SOURCE_FILE:0) 

Es versucht, diesen Code auszuführen:

(read-string "{Apple Infinite Loop}") 

, die eine ungerade Anzahl von Tasten/Werte hat. Beachten Sie das Fehlen von Anführungszeichen um die einzelnen Hash-Schlüssel/Werte. Selbst wenn dieses Lesen funktioniert (d. H., Wenn Sie zufälligerweise eine gerade Anzahl von Parametern liefern), wird das, was es liest, keine Hash-Karte voller Strings sein, sondern Symbole. Sie erhalten also etwas anderes als das, was Sie ausgegeben haben.

user> (map class (keys (read-string (with-out-str (print {"foo bar" "baz quux"}))))) 
(clojure.lang.Symbol clojure.lang.Symbol) 
2

Denn sagen:

(def hashed-hobbits {:bilbo "Takes after his Mother's family" :frodo "ring bearer"}) 

Sie brauchen nur:

(spit "hobbitses.txt" hashed-hobbits) 

und es wieder zu lesen:

(def there-and-back-again (read-string (slurp "hobbitses.txt"))) 

Spieß/schlürfen hüllt alles in einem string aber die Verwendung von read-string auf dem slurp interpretiert die string zurück nach cl Code/Daten angeben. Funktioniert auch auf Trollish-Datenstrukturen!

+0

das ist großartig, danke – scape

Verwandte Themen