使用Core/async在Clojure中睡觉的理发问题,然后去
您好,谢谢您的任何帮助。我刚开始学习Clojure,并认为它很棒。以下是我睡眠理发问题的代码。我认为从核心/异步中掉落的缓冲器对于这个问题来说是完美的,虽然它似乎有效,但它永远不会停止。
发型和掉落的缓冲液似乎可以正常工作。
---编辑
它确实停止了。但是,我遇到了一个错误,试图检查零零的客户名称(我在下面的代码中指出了行)。似乎不能在零上进行
(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年创建的。
- 一家理发店带领客户。
- 客户以10到30毫秒的时间间隔到达。
- 理发店在候诊室有三把椅子。
- 理发店有一间理发师和一把理发椅。
- 当理发师的椅子空着时,顾客坐在椅子上,醒来理发师,并理发。
- 如果椅子被占用,所有新客户都会转身。
- 发型的二十毫秒。
- 客户收到理发后,他起身离开。
- 确定理发师在十秒钟内可以发出多少发型。
(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)
Hello and thank you for any help. I am just starting to learn Clojure, and think its amazing. Below is my codes for the sleeping barber problem. I thought that dropping-buffers from core/async would be perfect for this problem, and while it seems to work it never stops.
The haircuts and dropping buffer seem to work right.
---Edited
It does stop now. But I get an error trying to check customer-num for nil (I've noted the line in the code below). It seems like it can't do an if on a nil because it's nil!
(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
---End of edit
Also, how to get the return value of the number of haircuts to the calling operate-shop?
Sleeping barber problem as written up in Seven Languages in Seven Weeks. It was created by Edsger Dijkstra in 1965.
- A barber shop takes customers.
- Customers arrive at random intervals, from ten to thirty milliseconds.
- The barber shop has three chairs in the waiting room.
- The barber shop has one barber and one barber chair.
- When the barber’s chair is empty, a customer sits in the chair, wakes up the barber, and gets a haircut.
- If the chairs are occupied, all new customers will turn away.
- Haircuts take twenty milliseconds.
- After a customer receives a haircut, he gets up and leaves.
- Determine how many haircuts a barber can give in ten seconds.
(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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
没有运行您的代码来确认我的怀疑,我看到了您的实施问题。
首先是
的主体运营商店
以开头(
,您似乎打算作为分组机制。但是,当然,在clojure,(( fxy)
是您使用参数 x y 调用函数的方式。关闭!,然后调用关闭代理
- 到目前为止都打算 - 但随后调用alts!
(肯定不是函数)的结果,带有两个零论点。 <代码>(GO XYZ)。 href =“ https://github.com/clojure/core.async/blob/6ac8ed267bbc3cc43cc43e4e650f97c984666666b0c/src/src/src/main/main/clojure/clojure/clojure/clojure/core/core/core/core/core/cljl340 Tirmer错误。第二个是您的第一个
go-loop
没有终止条件。您将客户访问
好像是一个数字一样,但是如果频道关闭,则将是零:这就是您可以告诉频道关闭的方式。将其涉及减法应提出某种例外。取而代之的是,您应该检查结果是否为零,如果是,则在商店关闭时退出环路。Without running your code to confirm my suspicions, I see two problems with your implementation.
The first is that the body of
operate-shop
starts with((
, which you appear to intend as a grouping mechanism. But of course, in Clojure,(f x y)
is how you call the functionf
with argumentsx y
. So your implementation callsalts!
, then callsclose!
, then callsshutdown-agents
- all intended so far - but then calls the result ofalts!
(which surely is not a function) with two nil arguments. So you should get a ClassCastException once your shop closes. Normally I would recommend just removing the outer parens, but since you're using core.async you should wrap the body ingo
, as in(go x y z)
. Is this your real code? If you callalts!
outside of ago
context, as your snippet suggests, you can only get a runtime error.The second is that your first
go-loop
has no termination condition. You treatcustomer-num
as if it were a number, but if the channel is closed, it will be nil: that's how you can tell a channel is closed. Involving it in subtraction should throw some kind of exception. Instead, you should check whether the result is nil, and if so, exit the loop as the shop is closed.