Sleeping barber in Clojure - clojure

I'm implementing Sleeping barber using core.async. My current code is:
(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"))))
Is it a correct solution? Can it be improved to make it more Clojure-like?
I wanted to use alt! instead of alts! which makes code easier to read:
(defn barber [in]
(go-loop [served-customers 0]
(alt!
waiting-room (do (Thread/sleep 20)
(recur (inc served-customers)))
in served-customers)))
Runtime throws an exception: Can only recur from tail position. Can I still use alt!?

You could solve the alt!/recur problem by rewriting to:
(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)))

Related

macroexpand doseq in Babashka vs in Clojure

In Babashka v0.6.2, I can call macroexpand on the for macro and the output is something like this:
user=> (macroexpand '(for [i (range 10)] i))
(clojure.core/let [iter__1755__auto__ (clojure.core/fn iter__147 [s__148] (clojure.core/lazy-seq (loop [s__148 s__148] (clojure.core/let [s__148 (clojure.core/seq s__148)] (clojure.core/when s__148 (if (clojure.core/chunked-seq? s__148) (clojure.core/let [c__1753__auto__ (clojure.core/chunk-first s__148) size__1754__auto__ (clojure.core/int (clojure.core/count c__1753__auto__)) b__150 (clojure.core/chunk-buffer size__1754__auto__)] (if (loop [i__149 (clojure.core/int 0)] (if (clojure.core/< i__149 size__1754__auto__) (clojure.core/let [i (clojure.core/nth c__1753__auto__ i__149)] (do (clojure.core/chunk-append b__150 i) (recur (clojure.core/unchecked-inc i__149)))) true)) (clojure.core/chunk-cons (clojure.core/chunk b__150) (iter__147 (clojure.core/chunk-rest s__148))) (clojure.core/chunk-cons (clojure.core/chunk b__150) nil))) (clojure.core/let [i (clojure.core/first s__148)] (clojure.core/cons i (iter__147 (clojure.core/rest s__148))))))))))] (iter__1755__auto__ (range 10)))
However, if I do the same for doseq, then I get the same form back:
user=> (macroexpand '(doseq [i (range 10)] (println i)))
(doseq [i (range 10)] (println i))
But this latter expression works in Clojure as expected:
erdos.assert=> (macroexpand '(doseq [i (range 10)] (println i)))
(loop* [seq_2318 (clojure.core/seq (range 10)) chunk_2319 nil count_2320 0 i_2321 0] (if (clojure.core/< i_2321 count_2320) (clojure.core/let [i (.nth chunk_2319 i_2321)] (do (println i)) (recur seq_2318 chunk_2319 count_2320 (clojure.core/unchecked-inc i_2321))) (clojure.core/when-let [seq_2318 (clojure.core/seq seq_2318)] (if (clojure.core/chunked-seq? seq_2318) (clojure.core/let [c__4917__auto__ (clojure.core/chunk-first seq_2318)] (recur (clojure.core/chunk-rest seq_2318) c__4917__auto__ (clojure.core/int (clojure.core/count c__4917__auto__)) (clojure.core/int 0))) (clojure.core/let [i (clojure.core/first seq_2318)] (do (println i)) (recur (clojure.core/next seq_2318) nil 0 0))))))
Perhaps doseq is like a special form in Babashka? What is the reason for this distinction of doseq?
How should I modify macroexpand so that all macros are expanded?
Some things are indeed specially treated in the interpreter and not implemented as regular macros. This is an historical artifact from the early beginnings when babashka didn't even support macros. This may change in the future.
EDIT: this is now already fixed on master. Thanks for the PR erdos.

Throttle Functions with core.async

The number of possible executions of a function should be throttled. So after calling a function, any repeated call should be ignored within a time period. If there where calls in the meantime, the last one should be executed after the time period.
Here's my approach with core.async. The problem here is, that additional calls are summing up in the channel c. I'd need a channel with only one position inside, which will be overridden by put! everytime.
(defn throttle [f time]
(let [c (chan 1)]
(go-loop []
(apply f (<! c))
(<! (timeout time))
(recur))
(fn [& args]
(put! c (if args args [])))))
usage:
(def throttled (throttle #(print %) 4000))
(doseq [x (range 10)]
(throttled x))
; 0
;... after 4 seconds
; 9
Does anyone have an idea how to fix this?
Solution
(defn throttle [f time]
(let [c (chan (sliding-buffer 1))]
(go-loop []
(apply f (<! c))
(<! (timeout time))
(recur))
(fn [& args]
(put! c (or args [])))))
To solve your channel question you can use a chan with a sliding buffer:
user> (require '[clojure.core.async :as async])
nil
user> (def c (async/chan (async/sliding-buffer 1)))
#'user/c
user> (async/>!! c 1)
true
user> (async/>!! c 2)
true
user> (async/>!! c 3)
true
user> (async/<!! c)
3
that way only the last value put into the channel will be computed at the next interval.
You can use a debounce function.
I'll copy it out here:
(defn debounce [in ms]
(let [out (chan)]
(go-loop [last-val nil]
(let [val (if (nil? last-val) (<! in) last-val)
timer (timeout ms)
[new-val ch] (alts! [in timer])]
(condp = ch
timer (do (>! out val) (recur nil))
in (recur new-val))))
out))
Here only when in has not emitted a message for ms is the last value it emitted forwarded onto the out channel. While in continues to emit without a long enough pause between emits then all-but-the-last-message are continuously discarded.
I've tested this function. It waits 4 seconds and then prints out 9, which is nearly what you asked for - some tweaking required!
(defn my-sender [to-chan values]
(go-loop [[x & xs] values]
(>! to-chan x)
(when (seq xs) (recur xs))))
(defn my-receiver [from-chan f]
(go-loop []
(let [res (<! from-chan)]
(f res)
(recur))))
(defn setup-and-go []
(let [in (chan)
ch (debounce in 4000)
sender (my-sender in (range 10))
receiver (my-receiver ch #(log %))]))
And this is the version of debounce that will output as required by the question, which is 0 immediately, then wait four seconds, then 9:
(defn debounce [in ms]
(let [out (chan)]
(go-loop [last-val nil
first-time true]
(let [val (if (nil? last-val) (<! in) last-val)
timer (timeout (if first-time 0 ms))
[new-val ch] (alts! [in timer])]
(condp = ch
timer (do (>! out val) (recur nil false))
in (recur new-val false))))
out))
I've used log rather than print as you did. You can't rely on ordinary println/print functions with core.async. See here for an explanation.
This is taken from David Nolens blog's source code:
(defn throttle*
([in msecs]
(throttle* in msecs (chan)))
([in msecs out]
(throttle* in msecs out (chan)))
([in msecs out control]
(go
(loop [state ::init last nil cs [in control]]
(let [[_ _ sync] cs]
(let [[v sc] (alts! cs)]
(condp = sc
in (condp = state
::init (do (>! out v)
(>! out [::throttle v])
(recur ::throttling last
(conj cs (timeout msecs))))
::throttling (do (>! out v)
(recur state v cs)))
sync (if last
(do (>! out [::throttle last])
(recur state nil
(conj (pop cs) (timeout msecs))))
(recur ::init last (pop cs)))
control (recur ::init nil
(if (= (count cs) 3)
(pop cs)
cs)))))))
out))
(defn throttle-msg? [x]
(and (vector? x)
(= (first x) ::throttle)))
(defn throttle
([in msecs] (throttle in msecs (chan)))
([in msecs out]
(->> (throttle* in msecs out)
(filter #(and (vector? %) (= (first %) ::throttle)))
(map second))))
You probably also want to add a dedupe transducer to the channel.
I needed to pass a function to capture the args because I was using it for an input event and it was passing a mutable object. 🤷
(defn throttle-for-mutable-args [time f arg-capture-fn]
(let [c (async/chan (async/sliding-buffer 1))]
(async-m/go-loop []
(f (async/<! c))
(async/<! (async/timeout time))
(recur))
(fn [& args]
(async/put! c (apply arg-capture-fn (or args []))))))
And I use like
[:input
{:onChange (util/throttle-for-mutable-args
500
#(really-use-arg %)
#(-> % .-target .-value))}]

Failure to close channel causes indefinite blocking

Here is an example from http://www.braveclojure.com/core-async/ :
(defn hotdog-machine-v2 [hotdog-count]
(let [in (chan) out (chan)]
(go (loop [hc hotdog-count]
(if (> hc 0)
(let [input (<! in)]
(if (= 3 input)
(do
(>! out "hotdog")
(recur (dec hc)) )
(do
(>! out (Exception. "Not enough payment!"))
(recur hc))))
(do
(close! in)
(close! out)))))
[in out]))
(let [[in out] (hotdog-machine-v2 2)]
(>!! in "pocket lint")
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out))
)
If I leave out the channel-closing part, then this code hangs forever, why?
If I run this in the normal case with the close it prints this:
user> (let [[in out] (hotdog-machine-v2 2)]
(>!! in "pocket lint")
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out)))
#error {
:cause Not enough payment!
:via
[{:type java.lang.Exception
:message Not enough payment!
... stack trace here ...
[java.lang.Thread run Thread.java 724]]}
hotdog
hotdog
nil ;; <---- look here
That last nil is the result of the last read from out reading the value nil, which is being sent as a result of the channel closing because the machine is out of hotdogs. Without the close that last put (>!! in 3) blocks waiting for somthing to read from the chan which nobody is going to do. By default writes to core.async chans don't succeed in writing until someone is ready to read that value
If I take out the close, and take out the last write it does not print that nil, and does not block:
user> (let [[in out] (hotdog-machine-v2 2)]
(>!! in "pocket lint")
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out))
)
#error {
:cause Not enough payment!
:via
[{:type java.lang.Exception
:message Not enough payment!
:at ... stack trace here ...}
hotdog
hotdog

How do I rewrite (def) out of this Clojure code?

I have written a game loop based on deWitter's game loop.
However, I am unsure how to transfer it to a more functional state. I realize that there may need to be some mutable state left within the code but are there any general principles for cleaning up extraneous defs?
(ns beepboop.core)
(def ticks-per-second 25)
(def skip-ticks (/ 1000 ticks-per-second))
(def max-frameskip 5)
(defn update []
(println "Updating."))
(defn display [delta]
(println "Displaying with delta: " delta))
(defn -main []
(def *next-tick* (System/currentTimeMillis))
(while true
(def *loops* 0)
(while (and
(> (System/currentTimeMillis)
*next-tick*)
(< *loops*
max-frameskip))
(update)
(def *next-tick* (+ *next-tick* skip-ticks))
(def *loops* (+ *loops* 1)))
(display
(/ (+ (System/currentTimeMillis) skip-ticks (* -1 *next-tick*))
skip-ticks))))
You should use loop and recur for updating your loop variables:
(defn -main []
(loop [next-tick (System/currentTimeMillis)]
(let [next-next
(loop [next-tick next-tick
loops 0]
(if (and (> (System/currentTimeMillis) next-tick)
(< loops max-frameskip))
(do (update)
(recur (+ next-tick skip-ticks) (+ loops 1)))
next-tick))]
(display (/ (+ (System/currentTimeMillis) skip-ticks (- next-next))
skip-ticks))
(recur next-next))))

How to launch two threads and wait for them

I can launch two threads and they work, but synchronously. What am I missing to get these threads independently launched?
main, thread, and output
(defn -main
[& args]
(do
(let [grid-dim-in [0 5]
mr1-pos [\N 2 4]
mr2-pos [\N 1 5]
mr1-movs "LMLMMRMM"
mr2-movs "RMRMMMLM"]
(reset! grid-dim grid-dim-in)
(reset! mr1-id {:mr1 mr1-pos})
(reset! mr2-id {:mr2 mr2-pos})
(.start (Thread. (rover-thread mr1-id mr1-movs update-work-block)))
(.start (Thread. (rover-thread mr2-id mr2-movs update-work-block))))))
(defn rover-thread [id movs update-ref]
(let [id-key (keys #id)
id-vals (vals #id)]
(doseq [mov movs]
(println "Rover " id-key " is moving ")
(let [new-mov (determine-rover-move (first id-vals) mov)]
(move-rover id new-mov update-ref)
(print "Rover ")
(print (first id-key))
(print " is at ")
(println new-mov)
(Thread/sleep (rand 1000)))))
Rover :mr1 is at [E 2 4]
Rover (:mr1) is moving
Rover :mr1 is at [N 2 5]
Rover (:mr1) is moving
Rover :mr1 is at [N 2 5]
Finished on Thread[main,5,main]
Rover (:mr2) is moving
Rover :mr2 is at [E 1 5]
Rover (:mr2) is moving
Rover :mr2 is at [N 1 6]
Take a close look at these two lines:
(.start (Thread. (rover-thread mr1-id mr1-movs update-work-block)))
(.start (Thread. (rover-thread mr2-id mr2-movs update-work-block))))))
This code evaluates the (rover-thread mr1-id mr1-movs update-work-block) first, and passes the result of that to the constructor of Thread, which is not what you want.
Here's a simple function to illustrate the principle. This doesn't work, because the (f ...) is evaluated before its result it passed to the Thread constructor:
(defn run-thread-thing-wrong []
(let [f (fn [n s]
(doseq [i (range n)]
(prn s i)
(Thread/sleep (rand 1000))))]
(.start (Thread. (f 10 "A")))
(.start (Thread. (f 10 "B"))))
nil)
Here's a version that does work. A function is passed to the Thread constructor instead:
(defn run-thread-thing []
(let [f (fn [n s]
(doseq [i (range n)]
(prn s i)
(Thread/sleep (rand 1000))))]
(.start (Thread. (fn [] (f 10 "A"))))
(.start (Thread. (fn [] (f 10 "B")))))
nil)
Note: instead of (fn [] ....) you can use the short form #(....) for anonymous functions.
Here's another version that does the same, but with a future instead of manually creating threads:
(defn run-thread-thing []
(let [f (fn [n s]
(doseq [i (range n)]
(prn s i)
(Thread/sleep (rand 1000))))]
(future (f 10 "A"))
(future (f 10 "B")))
nil)
Note that in this case, you pass a form to future instead of a function.
This seems like a really good place to use Clojure's agent feature. I am not qualified to fully explain how to use them, but a really good example of their usage can be found here. Starting threads using agents is dead-easy, and I think it is more idiomatic.
The code would look something like,
(def rover1 (agent [mr1-posn mr1-movs mr1-id]))
(def rover2 (agent [mr2-posn mr2-movs mr2-id]))
(defn rover-behave [[posn movs id]]
(send-off *agent* #'rover-behave)
(. Thread (sleep 1000))
(let [new-mov (determine-rover-move posn movs id)
new-posn (posn-after-move posn new-mov)]
;return value updates state of agent
[new-posn movs id]
)
)
(send-off rover1 rover-behave)
(send-off rover2 rover-behave)