I am trying to implement the dining philosopher example in clojure. For some reasons my program always dies with an exception saying
"java.lang.UnsupportedOperationException: nth not supported on this type: Boolean"
I can't understand this error message since I already tried to get boolean values from a list which worked perfectly with nth
I guess the error happens in the if statement in the function philosopher-thread
Console Prints:
Code:
(ns dining-philosphers.core
(:gen-class))
(defn think [n]
(println (str n " is thinking"))
(Thread/sleep (rand 1000))
(println (str n " after sleep"))
)
(defn eat [n]
(println (str n " is eating"))
(Thread/sleep (rand 1000))
)
(def isEating (atom '(false false false false false)))
(defn philosopher-thread [n]
(Thread. #(
(while true (do
(think n)
(println (str n " after think"))
(if (or (nth @isEating (mod (- n 1) 5)) (nth @isEating (mod (+ n 1) 5)))
(println "is waiting for neighbour")
(
do
(println (str n " swap"))
(swap! isEating (fn [l] assoc l n true))
(eat n)
(swap! isEating (fn [l] assoc l n true))
)
)
)
)
)
)
)
(defn -main [& args]
(let [threads (map philosopher-thread (range 5))]
(doseq [thread threads] (.start thread))
(doseq [thread threads] (.join thread))))
You're missing some parens here:
(swap! isEating (fn [l] assoc l n true))
should be
(swap! isEating (fn [l] (assoc l n true)))
The first will evaluate assoc
, l
, n
and true
in order, and return the value of the last expression (true
)
There is still a problem, which is that you can't assoc
onto a list. I suggest using a vector instead:
(def isEating (atom [false false false false false]))