I have just started playing with Clojure and the first thing I thought I'd try is storing and retrieving a list of structs, like in Suart Halloway's example here.
我刚刚开始玩Clojure,我认为我尝试的第一件事就是存储和检索结构列表,就像Suart Halloway的例子一样。
My spit/slurp of a hash of structs works fine with, if I use struct instances without spaces in the attribute strings like the following:
如果我在属性字符串中使用没有空格的struct实例,那么我的spit / slurp结构哈希工作正常,如下所示:
(struct customer "Apple" "InfiniteLoop")
But if I use this:
但如果我使用这个:
(struct customer "Apple" "Infinite Loop 1")
I get an error:
我收到一个错误:
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
Depending on the amount of the fields in the struct, I might also just get a part of the string as an attribute name instead of the error. For example :Loop 1
根据结构中字段的数量,我可能只是将字符串的一部分作为属性名而不是错误。例如:循环1
I use a store-function like this:
我使用像这样的商店功能:
(defn store-customer-db [customer-db filename]
(spit filename (with-out-str (print customer-db))))
And a read-function like this:
和这样的读取函数:
(defn load-db [filename]
(with-in-str (slurp filename)(read)))
From the output file of spit I can see that the print doesn't give double quotes to the strings which seems to be a problem for slurp. What would be the correct solution for this?
从吐出的输出文件中我可以看到打印不会给字符串加双引号,这似乎是一个问题。对此有什么正确的解决方案?
My Clojure version is 1.0, and the contrib is a few weeks old snapshot.
我的Clojure版本是1.0,而contrib是一个几周的快照。
2 个解决方案
#1
print
and println
are meant for human-readable output. If you want to print something that's meant to be read in again later, use pr
or prn
.
print和println用于人类可读的输出。如果您想要打印稍后要再次读取的内容,请使用pr或prn。
user> (read-string (with-out-str (prn {"Apple" "Infinite Loop"})))
{"Apple" "Infinite Loop"}
Whereas:
user> (read-string (with-out-str (print {"Apple" "Infinite Loop"})))
java.lang.ArrayIndexOutOfBoundsException: 3 (NO_SOURCE_FILE:0)
It's trying to run this code:
它正在尝试运行此代码:
(read-string "{Apple Infinite Loop}")
which has an odd number of keys/values. Note the lack of quotation marks around the individual hash keys/values. Even if this read works (i.e. if you coincidentally supply an even number of parameters), what it reads won't be a hash-map full of Strings, but rather Symbols. So you'll be getting back something other than what you output.
它具有奇数个键/值。请注意,各个散列键/值周围缺少引号。即使这个读取工作(即如果你巧合地提供了偶数个参数),它所读取的内容将不是一个充满字符串的哈希图,而是符号。因此,除了输出内容之外,您将获得其他内容。
user> (map class (keys (read-string (with-out-str (print {"foo bar" "baz quux"})))))
(clojure.lang.Symbol clojure.lang.Symbol)
#2
For, say:
(def hashed-hobbits {:bilbo "Takes after his Mother's family" :frodo "ring bearer"})
You only need:
你只需要:
(spit "hobbitses.txt" hashed-hobbits)
and to read it back:
读回来:
(def there-and-back-again (read-string (slurp "hobbitses.txt")))
spit/slurp wraps it all in a string but using read-string on the slurp interprets the string back to clojure code/data. Works on trollish data structures too!
spit / slurp将它全部包装在一个字符串中,但在slurp上使用read-string将字符串解释为clojure代码/数据。也适用于数据结构!
#1
print
and println
are meant for human-readable output. If you want to print something that's meant to be read in again later, use pr
or prn
.
print和println用于人类可读的输出。如果您想要打印稍后要再次读取的内容,请使用pr或prn。
user> (read-string (with-out-str (prn {"Apple" "Infinite Loop"})))
{"Apple" "Infinite Loop"}
Whereas:
user> (read-string (with-out-str (print {"Apple" "Infinite Loop"})))
java.lang.ArrayIndexOutOfBoundsException: 3 (NO_SOURCE_FILE:0)
It's trying to run this code:
它正在尝试运行此代码:
(read-string "{Apple Infinite Loop}")
which has an odd number of keys/values. Note the lack of quotation marks around the individual hash keys/values. Even if this read works (i.e. if you coincidentally supply an even number of parameters), what it reads won't be a hash-map full of Strings, but rather Symbols. So you'll be getting back something other than what you output.
它具有奇数个键/值。请注意,各个散列键/值周围缺少引号。即使这个读取工作(即如果你巧合地提供了偶数个参数),它所读取的内容将不是一个充满字符串的哈希图,而是符号。因此,除了输出内容之外,您将获得其他内容。
user> (map class (keys (read-string (with-out-str (print {"foo bar" "baz quux"})))))
(clojure.lang.Symbol clojure.lang.Symbol)
#2
For, say:
(def hashed-hobbits {:bilbo "Takes after his Mother's family" :frodo "ring bearer"})
You only need:
你只需要:
(spit "hobbitses.txt" hashed-hobbits)
and to read it back:
读回来:
(def there-and-back-again (read-string (slurp "hobbitses.txt")))
spit/slurp wraps it all in a string but using read-string on the slurp interprets the string back to clojure code/data. Works on trollish data structures too!
spit / slurp将它全部包装在一个字符串中,但在slurp上使用read-string将字符串解释为clojure代码/数据。也适用于数据结构!