你好,谢谢您的帮助。我才刚开始学Clojure,我觉得很神奇。下面是我的睡眠理发师问题的密码。我认为从核心/异步中删除缓冲区将是解决这个问题的完美方法,虽然它似乎可以工作,但它永远不会停止。
理发和减掉的缓冲似乎是正确的。
--编辑
,它现在停下来了。但是,我在检查customer是否为nil时遇到了一个错误(我注意到了下面代码中的一行)。似乎它不能在零上做一个if,因为它是0!
(if (not (nil? customer-num)) ;; throws error => Cannot invoke "clojure.lang.IFn.invoke()" because the return value of "clojure.lang.IFn.invoke(Object)" is null
--编辑的末尾
另外,怎样才能得到理发次数的返回值呢?
七周内用七种语言写的睡眠理发师问题。它是由Edsger Dijkstra于1965年创建的。
(ns sleepbarber
(:require [clojure.core.async
:as a
:refer [>! <! >!! <!! go go-loop chan dropping-buffer close! thread
alt! alts! alts!! timeout]]))
(def barber-shop (chan (dropping-buffer 3))) ;; no more than 3 customers waiting
(defn cut-hair []
(go-loop [haircuts 0]
(let [customer-num (<! barber-shop)]
(if (not (nil? customer-num)) ;; throws error => Cannot invoke "clojure.lang.IFn.invoke()" because the return value of "clojure.lang.IFn.invoke(Object)" is null
(do (<! (timeout 20)) ;; wait for haircut to finish
(println haircuts "haircuts!" (- customer-num haircuts) "customers turned away!!")
(recur (inc haircuts)))
haircuts))))
(defn operate-shop [open-time]
((let [[_ opening] (alts!! [(timeout open-time)
(go-loop [customer 0]
(<! (timeout (+ 10 (rand-int 20)))) ;; wait for random arrival of customers
(>! barber-shop customer)
(recur (+ customer 1)))])]
(close! barber-shop)
(close! opening)
)))
(cut-hair)
(operate-shop 2000)
发布于 2022-06-07 17:23:31
如果没有运行代码来确认我的怀疑,我就会发现您的实现有两个问题。
首先,operate-shop
的主体以((
开始,您似乎打算将其作为分组机制。当然,在Clojure中,(f x y)
是如何使用参数x y
调用函数f
的。因此,您的实现调用了alts!
,然后调用了close!
,然后调用了shutdown-agents
--到目前为止所有这些都是预期的--但是然后用两个零参数调用alts!
的结果(这肯定不是一个函数)。所以,一旦你的商店关门,你就应该得到一个ClassCastException。通常,我建议只移除外部的父类,但是由于您使用的是core.async,所以应该用go
包装身体,就像在(go x y z)
中那样。这是你真正的密码吗?如果您在alts!
上下文之外调用go
,正如您的代码片段所建议的那样,只能获得运行时错误。。
第二种情况是,您的第一个go-loop
没有终止条件。您将customer-num
视为一个数字,但如果通道关闭,它将为零:这是如何判断一个通道关闭。在减法中使用它应该会抛出某种异常。相反,您应该检查结果是否为零,如果是的话,在商店关闭时退出循环。
https://stackoverflow.com/questions/72534576
复制相似问题