如何使用clojure.edn/read获取文件中的对象序列?
Clojure 1.5引入了如何使用clojure.edn/read获取文件中的对象序列?,clojure,edn,Clojure,Edn,Clojure 1.5引入了Clojure.edn,其中包括一个需要回推读取器的读取功能 如果我想阅读前五个对象,我可以: (with-open [infile (java.io.PushbackReader. (clojure.java.io/reader "foo.txt"))] (binding [*in* infile] (let [edn-seq (repeatedly clojure.edn/read)] (dorun (take 5 (map println
Clojure.edn
,其中包括一个需要回推读取器的读取功能
如果我想阅读前五个对象,我可以:
(with-open [infile (java.io.PushbackReader. (clojure.java.io/reader "foo.txt"))]
(binding [*in* infile]
(let [edn-seq (repeatedly clojure.edn/read)]
(dorun (take 5 (map println edn-seq))))))
如何打印出所有对象?考虑到其中一些可能是零,似乎我需要检查EOF或类似的东西。我希望有一个类似于我从line seq
Use:eof key得到的对象序列
opts是一个可以包括以下键的映射::eof-value to
文件结束时返回。如果未提供,eof将引发异常
编辑:对不起,这不够详细!给你:
(with-open [in (java.io.PushbackReader. (clojure.java.io/reader "foo.txt"))]
(let [edn-seq (repeatedly (partial edn/read {:eof :theend} in))]
(dorun (map println (take-while (partial not= :theend) edn-seq)))))
应该可以了我又看了一遍。以下是我的想法:
(defn edn-seq
"Returns the objects from stream as a lazy sequence."
([]
(edn-seq *in*))
([stream]
(edn-seq {} stream))
([opts stream]
(lazy-seq (cons (clojure.edn/read opts stream) (edn-seq opts stream)))))
(defn swallow-eof
"Ignore an EOF exception raised when consuming seq."
[seq]
(-> (try
(cons (first seq) (swallow-eof (rest seq)))
(catch java.lang.RuntimeException e
(when-not (= (.getMessage e) "EOF while reading")
(throw e))))
lazy-seq))
(with-open [stream (java.io.PushbackReader. (clojure.java.io/reader "foo.txt"))]
(dorun (map println (swallow-eof (edn-seq stream)))))
edn seq
与clojure.edn/read
具有相同的签名,并保留了所有现有的行为,我认为这一点很重要,因为人们可能以不同的方式使用:eof
选项。一个包含EOF异常的单独函数似乎是一个更好的选择,尽管我不确定如何最好地捕获它,因为它显示为java.lang.RuntimeException
是的,就在文件里。哎呀。为EOF定义我自己的哨兵感觉有点脏,但也许我还没有弄明白为什么这是正确的解决方案。请参阅@bfontaine对其他答案的评论。具有内容独立性是有价值的,但您可以通过为:eof
键使用任何不可序列化为EDN的值来实现这一点。使用:eof
参数而不是测试异常的文本。旧问题/答案,但您为什么这么说?如果您使用:eof
实现,那么您就不是内容独立的。甚至:library/eof
也可能发生冲突。唯一可以避免的方法是强制用户将:eof值本身作为swallow eof
的一部分传递。EDN是Clojure值的子集,所以您所要做的就是给出一个不能像函数一样序列化为EDN的Clojure值。这一点很好。这似乎是正确的做法。我试着给出一个例子,但是注释中的格式很复杂。谢谢