7

line-seq の ClojureDocs エントリ ( http://clojuredocs.org/clojure_core/clojure.core/line-seq ) と Stack の質問 ( In Clojure 1.3, How to read and write a file ) に対する受け入れられた回答によると、 java.io.BufferedReader が渡された場合、line-seq は遅延 seq を返す必要があります。

しかし、これを REPL でテストすると、タイプは clojure.lang.Cons としてリストされます。以下のコードを参照してください。

=> (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

lazy-seq 呼び出しで line-seq 呼び出しをラップすると、lazy seq が得られますが、ドキュメントによると、これは必要ないはずです: とにかく line-seq は lazy seq を返す必要があります。

注: REPL (私は nrepl を使用しています) 内では、レイジー seq が完全に実現されているように見えます。ただし、Speclj でテストすると同じ問題が発生します。さらに、怠惰な seq を実現することは、とにかく何が起こっているのかと関係があるとは思いません。

編集:私は、コンスの末尾に怠惰なseqがあるとmobyteの回答が言った後、ソースコードをチェックしに行きました...

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 である理由を説明します。

4

1 に答える 1

3

Consすでに「テール」としてレイジー seq があるため、「ラップ」出力は必要ありません。

(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

編集。

注: REPL (私は nrepl を使用しています) 内では、レイジー seq が完全に実現されているようです。

正しくありません。あなたはそれをテストすることができます:

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

これは、repl が後で結果を実現して印刷しようとしたときに、完全には実現されておらず、既に閉じられているものがline-seq返されるためです。しかし、明示的に認識すれば、例外なく通常の結果が得られます。lazy-seqreader

(with-open [r (io/reader "/home/mobyte/2")] (doall (line-seq r)))
=> ...  output ...
于 2013-03-03T05:36:45.417 に答える