What's the return value of this function?

I am writing this function, but what is its return value.

(defn read-data [file]
  (let [code (subs (.getName file) 0 3)]
    (with-open [rdr (clojure.java.io/reader file)]
      (drop 1 (line-seq rdr)))))

(def d (read-data "data.db"))

      

Now well. But when I want to print this.

(clojure.pprint/pprint d)

      

I have an exception:

Exception in thread "main" java.lang.RuntimeException: java.io.IOException: Stream closed

      

so i was confused what happened? The return value is not a list? How to debug newbie in this situation?

Thank!

+3


source to share


3 answers


The problem is that it is line-seq

lazy and that the reader is closed by the time it is evaluated.

This means that all lines must be read within the area with-open

. One option is to force a full assessment line-seq

using doall

as shown below.



(drop 1 (doall (line-seq rdr)))

      

A potential problem with this approach is that you will get an OutOfMemoryError if the file is larger than the available memory. So, depending on what you are trying to accomplish, there may be other less memory-intensive solutions.

+3


source


As an example you can use a closure and a modified "line-seq" for an automatic reader:

(defn line-seq2 [^java.io.BufferedReader rdr]
  (if-let [line (.readLine rdr)]
    (cons line (lazy-seq (line-seq2 rdr)))
    (.close rdr)))

(defn my-reader [file]
  (let [lines (line-seq (clojure.java.io/reader file))]
    (fn [] lines)))

(def d (my-reader "data.db"))

      



now the variable "d" is a function:

user> (drop 1 (d))
=> ... file body except first line ...

      

+2


source


(drop 1 (line-seq rdr))

      

This string returns a sequence, either lazy or streamed. So basically the rdr reader is not actually readable when that line is executed, but when you try to access that sequence in your print method, rdr is read by a function line-seq

, but using with-open

that rdr is already closed when execution is done from with-open

.

Refer to doall

for the lazy sequence to be evaluated whenever it is created. I would suggest that you read about laziness in FP in general and sequences in particular for Clojure to better understand lazy evaluation.

+1


source







All Articles