Concurrency 未来永远不会解决问题,也不会兑现承诺

Concurrency 未来永远不会解决问题,也不会兑现承诺,concurrency,clojure,parallel-processing,functional-programming,lisp,Concurrency,Clojure,Parallel Processing,Functional Programming,Lisp,我在读一本书来教自己Clojure,这本书叫做Clojure,是为勇敢和真诚的人写的。第9章介绍了基本的并发编程,包括延迟、未来和承诺。本章末尾的第一个练习说明: “编写一个函数,将字符串作为参数,并使用slurp函数在Bing和Google上搜索它。您的函数应返回搜索返回的第一页的HTML” 我的解决办法如下: (defn search-bing-google [search-term] (let [search-results (promise)] (futu

我在读一本书来教自己Clojure,这本书叫做Clojure,是为勇敢和真诚的人写的。第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))
(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-bing-google "clojure")
(search "clojure" :bing :google)
第二项工作是:

“更新您的函数,以便使用由搜索引擎组成的第二个参数。”

我试图编辑我的第一个解决方案以满足新的参数要求,如下所示:

(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))
(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-bing-google "clojure")
(search "clojure" :bing :google)
但是,此实现与它的前一个实现不同,它挂起。由于第二个实现中的“映射”,似乎从未调用slurp。当我在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))

因为
map
会导致延迟求值,所以需要一些东西来实现它。在您的代码中,没有任何东西可以做到这一点,因此未来永远不会真正创建。不只是映射,而是执行以下操作:

(dorun (map ...

我没有在地图上使用
dorun
。相反,我使用
doseq
来迭代我的关键字列表。但感谢您让我走上了使用
dorun
doall
doseq
等进行强制求值的道路。