Clojure: сбой структур из файла завершается ошибкой со строковыми атрибутами, содержащими пробелы - PullRequest
7 голосов
/ 29 мая 2009

Я только начал играть с Clojure, и первое, что я решил попробовать, - это сохранить и получить список структур, как в примере Суарта Хэллоуэя здесь .

Мой хлам структур, с которым я работаю, работает нормально, если я использую экземпляры структуры без пробелов в строках атрибутов, как показано ниже:

(struct customer "Apple" "InfiniteLoop")

Но если я использую это:

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

Я получаю сообщение об ошибке:

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

В зависимости от количества полей в структуре, я мог бы просто получить часть строки в качестве имени атрибута вместо ошибки. Например: петля 1

Я использую функцию магазина следующим образом:

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

И функция чтения, подобная этой:

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

Из выходного файла spit я вижу, что печать не дает двойные кавычки для строк, что, похоже, является проблемой для slurp. Каково было бы правильное решение для этого?

Моя версия Clojure - 1.0, а вклад - снимок нескольких недель.

Ответы [ 2 ]

10 голосов
/ 29 мая 2009

print и println предназначены для удобочитаемого вывода. Если вы хотите распечатать что-то, что будет прочитано позже, используйте pr или prn.

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

Принимая во внимание:

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

Он пытается запустить этот код:

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

, который имеет нечетное количество ключей / значений. Обратите внимание на отсутствие кавычек вокруг отдельных хеш-ключей / значений. Даже если это чтение работает (т. Е. Если вы случайно указали четное число параметров), оно будет не хэш-картой, полной строк, а символами. Таким образом, вы будете получать что-то, кроме того, что вы выводите.

user> (map class (keys (read-string (with-out-str (print {"foo bar" "baz quux"})))))
(clojure.lang.Symbol clojure.lang.Symbol)
2 голосов
/ 09 января 2013

Для, скажем,

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

Вам нужно только:

(spit "hobbitses.txt" hashed-hobbits)

и прочитать его обратно:

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

spit / slurp оборачивает все это в строку, но использование read-string в slurp интерпретирует строку обратно в код / ​​данные замыкания. Работает и на троллейных структурах данных!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...