I ran into an interesting situation today, and although I have
realized my mistake, thought I would share as I think it is a good
illustration of a scenario where one may mistakenly rely on "expected"
functional "correctness" when you don't fully consider the
ramifications of lazy sequences and deferred execution.
Phew.
Consider the following code:
(let [storage (open-storage *storage-path*)
posts (get-last-n-posts 10 storage)]
(close-storage storage)
posts)
The function, get-last-n-posts, returns a list, and initially was
built up with loop and recur. We open a database, get stuff, close the
database, and return the retrieved records.
All is happy and well.
Then I changed get-last-n-posts, and the change resulted in a lazy
sequence being returned (because of map).
After the change, things no longer worked. I could tell that my code
was trying to access a closed database connection. But from the code
snippet above it was not immediately clear where the error in logic
lied.
The return value, posts, now being a lazy sequence of calls to
database record retrieval, breaks when you access the items in the
sequence, because the database is *already* closed.
To correct, you have to call doall on the lazy seq to ensure all items
in the sequence are "filled" in by database access *before* the
connection is closed, like so:
(let [storage (open-storage *storage-path*)
posts (doall (get-last-n-posts 10 storage))]
(close-storage storage)
posts)
Deferred evaluation/execution got me here.
Joubert
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---