2

我正在讀一本書來教自己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)) 

可以稱得上像:

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

但是這種實現掛起不像它的前身。它好像在第二次實現中由於「映射」而從不被調用。任何人都可以幫我弄清楚,當我在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)) 

回答

3

因爲map導致懶惰的評價,東西爲了實現它而需要。在你的代碼中,這些都不是,所以期貨從來沒有真正創造過。而不僅僅是map,請執行:

(dorun (map ... 
+0

我沒有在地圖上使用'dorun'。相反,我使用'doseq'來迭代關鍵字列表。但是,謝謝你讓我在「dorun」,「doall」,「doseq」等方面進行強制評估。 – webermaster