为什么line-seq返回clojure.lang.Cons而不是clojure.lang.LazySeq? [英] Why is line-seq returning clojure.lang.Cons instead of clojure.lang.LazySeq?

查看:354
本文介绍了为什么line-seq返回clojure.lang.Cons而不是clojure.lang.LazySeq?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据针对line-seq的ClojureDocs条目( http://clojuredocs.org/ clojure_core / clojure.core / line-seq )和Stack问题的接受答案(在Clojure 1.3中,如何读取和写入文件),当传递java.io.BufferedReader时,line-seq应该返回一个延迟seq。

According to the ClojureDocs entry for line-seq (http://clojuredocs.org/clojure_core/clojure.core/line-seq) and the accepted answer for the Stack question (In Clojure 1.3, How to read and write a file), line-seq should return a lazy seq when passed a java.io.BufferedReader.

但是当我在REPL中测试这个时,类型被列为clojure.lang.Cons。请参阅下面的代码:

However when I test this in the REPL, the type is listed as clojure.lang.Cons. See the code below:

=> (ns stack-question
     (:require [clojure.java.io :as io]))
nil
=> (type (line-seq (io/reader "test-file.txt")))
clojure.lang.Cons
=> (type (lazy-seq (line-seq (io/reader "test-file.txt"))))
clojure.lang.LazySeq

在延迟seq调用中换行line-seq调用给出了一个延迟seq,但根据文档,这不应该是:line-seq应该返回一个懒惰seq无论如何。

Wrapping up the line-seq call in a lazy-seq call gives a lazy seq, but according to the docs, this shouldn't be necessary: line-seq should return a lazy seq anyway.

注意:
在REPL内部(我使用nrepl)似乎懒惰seqs完全实现,所以我想也许是只是REPL的一个怪癖;然而同样的问题存在,当我用Speclj测试。另外,我不认为实现一个惰性的seq也与正在发生的事情有关。

Note: Inside the REPL (I'm using nrepl) it seems that lazy seqs get fully realized, so I thought perhaps it was just a quirk of the REPL; however the same problem exists when I test it with Speclj. Plus, I don't think realizing a lazy seq has to do with what is going on anyway.

编辑:
所以我去检查源代码在mobyte的回答后有一个懒惰的seq在尾巴的利弊...

So I went to check the source code after mobyte's answer said there is a lazy seq in the tail of the cons...

1   (defn line-seq
2     "Returns the lines of text from rdr as a lazy sequence of strings.
3     rdr must implement java.io.BufferedReader."
4     {:added "1.0"}
5     [^java.io.BufferedReader rdr]
6     (when-let [line (.readLine rdr)]
7       (cons line (lazy-seq (line-seq rdr)))))

调用cons会解释为什么line-seq的返回值的类型是clojure.lang.Cons 。

That call to cons would explain why the type of the return value of line-seq is clojure.lang.Cons.

推荐答案

您不需要wrap输出 Cons 它已经有延迟seq作为tail:

You don't need "wrap" output Cons because it already has lazy seq as "tail":

(type (line-seq (io/reader "test-file.txt")))
=> clojure.lang.Cons

(type (rest (line-seq (io/reader "test-file.txt"))))
=> clojure.lang.LazySeq

(type (cons 'a (rest (line-seq (io/reader "test-file.txt")))))
=> clojure.lang.Cons

编辑 b


注意:在REPL内部(我使用nrepl)看起来,延迟seqs得到
完全实现

Note: Inside the REPL (I'm using nrepl) it seems that lazy seqs get fully realized

不正确。您可以测试它:

Not correct. You can test it:

(with-open [r (io/reader "test-file.txt")] (line-seq r))
=> IOException Stream closed  java.io.BufferedReader.ensureOpen (BufferedReader.java:97)

这是因为 line-seq 返回 lazy-seq ,未完全实现 >已经关闭,当repl尝试实现结果以后打印它。但是如果你明确地意识到它会给正常结果没有任何异常:

It's because line-seq returns lazy-seq which is not fully realized and reader is already closed when repl tries to realize result later to print it. But if you realize it explicitly it would give normal result without any exceptions:

(with-open [r (io/reader "/home/mobyte/2")] (doall (line-seq r)))
=> ...  output ...

这篇关于为什么line-seq返回clojure.lang.Cons而不是clojure.lang.LazySeq?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆