我有以下代码:
(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))
我注意到let
评估必须是最后一次,否则就无法评估。这对我来说很困惑。尽管如此,当我在循环中实现它时,let
永远不会被评估,因为我认为recur最终会被推断出来。
(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))
))
我希望sleep
也位于此do
部分的末尾,但这确实没有用。
如何评估let
?是否与我map
的使用有关?我在这里误解了什么?
下载是一个功能:
(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)))))
答案 0 :(得分:6)
你被这个懒惰的小虫咬了一口:
我注意到评估必须是最后一次,否则就无法评估。
这是因为调用map的结果是惰性的,所以只有在读取结果时才会计算它。如果你把它放在最后,那么它将成为do
的返回值,其中由repl 打印,这导致它实际运行。
当我在循环中实现它时,永远不会评估:
while
将继续运行,直到表达式的返回值为false。在这种情况下,表达式的返回值是一个惰性序列,如果有人看过它,会导致某些页面被下载。在这种情况下,没有任何内容会查看结果,因此没有任何内容被下载,并且因为它不是假的,它只是一直在运行。
如何让我们评估?:
将调用包装在(doall (map ... ....))
中以使得惰性序列得到评估。
答案 1 :(得分:1)
我对正在发生的事情的猜测:
map
是一个惰性函数,所以当它是do
中的最后一项时,它会被评估,因为这是do
返回的内容。如果它不是do
中的最后一个,那么它的返回值没有被使用,所以它没有得到评估。
I ran into something similar myself
尝试使用doseq
代替map
。