Why does line-seq return clojure.lang.Cons instead of clojure.lang.LazySeq?

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

However, when I test this in REPL, the type is listed as clojure.lang.Cons. See 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 

Ending a line-seq call with a lazy-seq call gives a lazy seq, but according to the docs, this is not necessary: ​​line-seq should return a lazy seq anyway.

Note: Inside the REPL (I use nrepl) it seems that lazy seqs are fully implemented, so I thought it was just a REPL quirk; however, the same problem exists when I test it with Speclj. Also, I don't think the implementation of lazy seq is related to what happens anyway.

EDIT: So I went to check the source code after mobyte's answer, said there is a lazy seq at the tail of the minuses ...

 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))))) 

This cons call will explain why the return type of the -seq string is clojure.lang.Cons.

+4
source share
1 answer

You do not need to wrap Cons output 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 

Change

Note: Inside REPL (I use nrepl) it seems that lazy queries are fully implemented

Wrong. You can check it out:

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

This is because line-seq returns lazy-seq , which is not fully implemented, and the reader already closed when repl tries to implement the result later to print it. But if you clearly understand this, it will give a normal result without any exceptions:

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

Source: https://habr.com/ru/post/946901/


All Articles