Reputation: 7394
Just starting to learn Clojure with 100 doors problem. Im getting a cast error:
java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn
Here is my code:
(defn doors [n]
(loop [n n
acc (repeat n false)]
(if (= n 0)
(open-doors acc)
(do
(let
[yy (map-every-nth not acc n)]
(recur (dec n) (acc yy)))))))
(defn map-every-nth [f coll n]
(map-indexed #(if (zero? (mod (inc %1) n)) (f %2) %2) coll))
(defn open-doors [d]
(for [doors d
n (iterate inc 0)
:when d]
n))
(doors 100)
Upvotes: 1
Views: 354
Reputation: 2121
Here is a solution
(defn map-every-nth [f n coll]
(map-indexed
#(if (zero? (mod (inc %) n))
(f %2)
%2)
coll))
(defn doors []
(let [n 100]
(loop [p 1
state (repeat n false)]
(if (>= p 100)
state
(recur
(inc p)
(map-every-nth not p state))))))
Upvotes: 0
Reputation: 7599
Remember that Clojure will try to execute every list that it encounters:
(+ 1 2)
Here symbol +
is bound to function, thus the form (+ 1 2)
is executed successfully. Even quote doesn't cancel the rule:
'(+ 1 2) => (quote (+ 1 2))
Quote form gets executed and returns its contents as result. So first element of every list in Clojure must be something executable: symbol bound to macro or function, or special operator.
In your example we see:
(acc yy)
acc
is a lazy sequence, result of (repeat n false)
. It cannot be executed, thus you get an error.
Note, that there is a recursive call in your function, so arguments of recur
are arguments of a function. In Clojure arguments of a function get evaluated before using. Arguments of a macro do not.
Upvotes: 3