2

Я читаю книгу, чтобы научить себя 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)) 

ответ

3

Потому что map приводит к ленивым вычислениям, что-то требуется для его реализации. В вашем коде ничего не делает, поэтому фьючерсы никогда не создаются. Вместо map, do:

(dorun (map ... 
+0

Я не использовал 'dorun' с картой. Вместо этого я использовал «доза», чтобы перебирать список ключевых слов. Но спасибо за то, что устроили меня на пути, рассматривая принудительную оценку с помощью 'dorun',' doall', 'doseq' и т. Д. – webermaster

Смежные вопросы