user3139545
user3139545

Reputation: 7394

Error trying to cast LazySeq to IFn

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

Answers (2)

RedDeckWins
RedDeckWins

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

Mark Karpov
Mark Karpov

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

Related Questions