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!
source to share
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.
source to share
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 ...
source to share
(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.
source to share