我正在读一本书来教自己Clojure称为 Clojure for the Brave and True 。第9章介绍了基本的并发编程,包括延迟,期货和承诺。本章末尾的第一个练习是:
"编写一个以字符串作为参数的函数,并使用slurp函数在Bing和Google上搜索它。您的函数应返回搜索"
返回的第一页的HTML我的解决方案如下:
(defn search-bing-google
[search-term]
(let [search-results (promise)]
(future (deliver search-results
(slurp (str "https://www.bing.com/search?q%3D" search-term))))
(future (deliver search-results
(slurp (str "https://www.google.com/search?q%3D" search-term))))
@search-results))
可以这样称呼:
(search-bing-google "clojure")
第二项练习如下:
"更新你的功能,所以它需要第二个参数,包括要使用的搜索引擎。"
我尝试编辑我的第一个解决方案以满足新的参数要求,如下所示:
(def search-engines
{:bing "https://www.bing.com/"
:google "https://www.google.com/"})
(defn search
[search-term & engines]
(let [results (promise)]
(map #(future (deliver results
(slurp (str (% search-engines)
"search?q%3D"
search-term)))) engines)
@results))
可以像:
一样调用(search "clojure" :bing :google)
然而,这个实现与它的前身不同。它似乎因为" map"而从未被调用过。在第二个实现中。任何人都可以帮我弄清楚当我在REPL中加载它并执行它时导致它挂起的原因是什么?
编辑:
通过下面的Josh的回答,我提出了以下解决方案,使用doseq
代替dorun
和map
不再挂起:
(def search-engines
{:bing "https://www.bing.com/"
:google "https://www.google.com/"})
(defn search
[search-term & engines]
(let [results (promise)]
(doseq [engine engines]
(future (deliver results
(slurp (str (engine search-engines)
"search?q%3D"
search-term)))))
@results))
答案 0 :(得分:3)
因为map
会导致延迟评估,所以需要一些东西来实现它。在你的代码中,没有任何东西,所以期货永远不会真正创建。不只是map
,而是:
(dorun (map ...