Reputation: 707
I have the following code:
(do
(prn "sleeping for 60 seconds")
(Thread/sleep 6000)
(prn "kicking off calendar downloads @ " (new java.util.Date))
(let [links (map #(clojure.string/split % #",") (clojure.string/split (clojure.string/replace (slurp "calendars.csv") #"\r" "") #"\n"))]
(map download links))
I noticed let
evaluation must be last or else it does not get evaluated. This is confusing to me. Nonetheless when I implement this in a loop, let
is never evaluated since I think recur ends up being inferred.
(while
(do
(prn "sleeping for 60 seconds")
(Thread/sleep 60000)
(prn "kicking off calendar downloads @ " (new java.util.Date))
(let [links (map #(clojure.string/split % #",") (clojure.string/split (clojure.string/replace (slurp "calendars.csv") #"\r" "") #"\n"))]
(map download links))
))
I'd prefer for sleep
to be at the end of this do
section as well, but that is moot really.
How can I get let
to evaluate? Does it have to do with my use of map
? What am I misinterpreting here?
Download is a function:
(defn download [[calname ics]]
(prn "attempting cal download: " calname)
(try (spit (str dest calname ".csv") (slurp ics))
(catch Exception e (str "caught exception: " (.getMessage e)))))
Upvotes: 2
Views: 240
Reputation: 91554
you have been bitten by the lazy bug:
I noticed let evaluation must be last or else it does not get evaluated.
this is because the result of calling map is lazy so it is only evaluated if something reads the result. If you put it last, then it becomes the return value of the do
which gets printed by the repl, which causes it to actually run.
when I implement this in a loop, let is never evaluated:
while
will keep running until the return value of the expression is false. In this case the return value of the expression is a lazy sequence that would cause some pages to be downloaded if anyone ever looked at it. In this case nothing looks at the result so nothing is ever downloaded, and since it's not false it just keeps running.
How can I get let to evaluate?:
wrap the calls to map in (doall (map ... ....))
to cause the lazy sequence to be evaluated.
Upvotes: 6
Reputation: 1705
My guess at what is happening:
map
is a lazy function, so when it's the last item in the do
, it is getting evaluated since that's what is being returned by the do
. If it's not the last thing in the do
, then its return value is not being used and so it's not getting evaluated.
I ran into something similar myself.
Try using doseq
instead of map
.
Upvotes: 1