【问题标题】:Futures never resolve and deliver to promise期货永远不会解决并兑现承诺
【发布时间】:2017-05-31 14:12:51
【问题描述】:

我正在阅读一本书来自学 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)

然而,这个实现与它的前身不同。就好像由于第二个实现中的“地图”而从未调用过 slurp。当我在 REPL 中加载并执行它时,谁能帮我弄清楚是什么导致它挂起?

编辑:

根据下面 Josh 的回答,我想出了以下解决方案,不再使用 doseq 而不是 dorunmap 挂起:

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

【问题讨论】:

    标签: concurrency clojure parallel-processing functional-programming lisp


    【解决方案1】:

    因为map 导致延迟评估,所以需要一些东西来实现它。在您的代码中,没有这样做,因此从未实际创建期货。不要只是map,而是:

    (dorun (map ...
    

    【讨论】:

    • 我没有在地图上使用dorun。相反,我使用doseq 来遍历我的关键字列表。但是感谢您让我走上通过dorundoalldoseq 等进行强制评估的道路。
    猜你喜欢
    • 2016-05-06
    • 2019-11-29
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多