在Clojure睡觉理发师

时间:2016-07-31 06:46:36

标签: clojure core.async

我正在使用core.async实施Sleeping barber。我目前的代码是:

(def workingtime 10000)

(defn barber [in waiting-room]
  (go-loop [served-customers 0]
           (let [[v] (alts! [waiting-room in])]
             (if (= v :close)
               served-customers
               (do (Thread/sleep 20)
                   (recur (inc served-customers)))))))

(defn customers [in waiting-room]
  (go-loop [customers-overall 0]
           (let [customer-arrival-interval (timeout (+ 10 (rand-int 20)))
                 [v] (alts! [in customer-arrival-interval])]
             (if (= v :close)
               customers-overall
               (do (>! waiting-room :customer)
                   (recur (inc customers-overall)))))))

(defn -main [& args]
  (let [in (chan)
        waiting-room (chan (dropping-buffer 3))
        barber-ch (barber in waiting-room)
        customers-ch (customers in waiting-room)]
    (println "opening the shop for 10 seconds...")
    (Thread/sleep workingtime)
    (>!! in :close)
    (>!! in :close)
    (println "closing the shop...")
    (println (str "Served " (<!! barber-ch) " customers"))
    (println (str "Overall " (<!! customers-ch) " customers came"))))

这是一个正确的解决方案吗?可以改进它以使它更像Clojure - 像吗?

我想使用alt!代替alts!,这使代码更易于阅读:

(defn barber [in]
  (go-loop [served-customers 0]
           (alt!
             waiting-room (do (Thread/sleep 20)
                              (recur (inc served-customers)))
             in served-customers)))

运行时抛出异常:Can only recur from tail position。我还可以使用alt!吗?

1 个答案:

答案 0 :(得分:0)

您可以通过重写为:

来解决alt! / recur问题
(defn barber [in]
  (go-loop [served-customers 0]
    (if (= :waiting-room
           (a/alt!
             waiting-room ([result] :waiting-room) ;; you could also use result if needed
             in ([result] :in))) ;; same here
      (do (Thread/sleep 20)
          (recur (inc served-customers)))
      served-customers)))
相关问题