Я читаю книгу, чтобы научить себя Clojure под названием Clojure for the Brave and True. В главе 9 рассматриваются основные параллельные программы, включая задержки, фьючерсы и обещания. В первом упражнении в конце главы говорится:Фьючерсы никогда не разрешат и не доставляют пообещать
«Напишите функцию, которая берет строку в качестве аргумента и ищет ее на Bing и Google с помощью функции slurp. Ваша функция должна возвращать 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")
Второе упражнение стат ed as:
«Обновите свою функцию, чтобы получить второй аргумент, состоящий из поисковых систем».
Я попытался изменить свое первое решение для удовлетворения новых требований аргумента следующим образом:
(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 и выполняю его?
EDIT:
С ответом Джоша ниже я придумал следующее решение, которое больше не нависает с использованием 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))
Я не использовал 'dorun' с картой. Вместо этого я использовал «доза», чтобы перебирать список ключевых слов. Но спасибо за то, что устроили меня на пути, рассматривая принудительную оценку с помощью 'dorun',' doall', 'doseq' и т. Д. – webermaster