2

我有以下代码:

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

2 回答 2

6

你被懒虫咬了:

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

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

  • 我怎样才能让评估?:
    包装对映射的调用以(doall (map ... ....))使惰性序列被评估。

于 2013-06-25T21:19:28.957 回答
1

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

map是一个惰性函数,因此当它是 中的最后一项时do,它会被评估,因为那是do. 如果它不是 中的最后一件事do,那么它的返回值不会被使用,因此它不会被评估。

我自己也遇到过类似的事情

尝试使用doseq而不是map.

于 2013-06-25T21:04:35.890 回答