在clojure中顽固循环,不要得到评估

时间:2013-06-25 20:49:48

标签: loops clojure

我有以下代码:

(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)))))

2 个答案:

答案 0 :(得分:6)

你被这个懒惰的小虫咬了一口:

  • 我注意到评估必须是最后一次,否则就无法评估。
    这是因为调用map的结果是惰性的,所以只有在读取结果时才会计算它。如果你把它放在最后,那么它将成为do的返回值,其中由repl 打印,这导致它实际运行。

  • 当我在循环中实现它时,永远不会评估
    while将继续运行,直到表达式的返回值为false。在这种情况下,表达式的返回值是一个惰性序列,如果有人看过它,会导致某些页面被下载。在这种情况下,没有任何内容会查看结果,因此没有任何内容被下载,并且因为它不是假的,它只是一直在运行。

  • 如何让我们评估?
    将调用包装在(doall (map ... ....))中以使得惰性序列得到评估。

答案 1 :(得分:1)

我对正在发生的事情的猜测:

map是一个惰性函数,所以当它是do中的最后一项时,它会被评估,因为这是do返回的内容。如果它不是do中的最后一个,那么它的返回值没有被使用,所以它没有得到评估。

I ran into something similar myself

尝试使用doseq代替map