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 clojure@googlegroups.com
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to