Database Reference
In-Depth Information
Oops! At the point where the function returns the lazy sequence, it hasn't read any
data yet. However, when exiting the with-open form, the ile is automatically
closed. What happened?
First, the ile is opened and passed to read-csv , which returns a lazy sequence.
The lazy sequence is returned from with-open , which closes the ile. Finally, the
REPL tries to print out this lazy sequence. Now, read-csv tries to pull data from
the ile. However, at this point the ile is closed, so the IOException is raised.
This is a pretty common problem for the irst draft of a function. It especially seems
to bite me whenever I'm doing database reads, for some reason.
2.
So, in order to ix this, we'll just force all of the lines to be read:
(defn lazy-read-bad-2 [csv-file]
(with-open [in-file (io/reader csv-file)]
(doall
(csv/read-csv in-file))))
This will return data, but everything gets loaded into the memory. Now, we have
safety but no laziness.
3.
Here's how we can get both:
(defn lazy-read-ok [csv-file]
(with-open [in-file (io/reader csv-file)]
(frequencies
(map #(nth % 2) (csv/read-csv in-file)))))
This is one way to do it. Now, we've moved what we're going to do to the data into the
function that reads it. This works, but it has a poor separation of concerns. It is both
reading and processing the data, and we really should break these into two functions.
4.
Let's try it one more time:
(defn lazy-read-csv [csv-file]
(let [in-file (io/reader csv-file)
csv-seq (csv/read-csv in-file)
lazy (fn lazy [wrapped]
(lazy-seq
(if-let [s (seq wrapped)]
(cons (first s) (lazy (rest s)))
(.close in-file))))]
(lazy csv-seq)))
This works! Let's talk about why.
 
Search WWH ::




Custom Search