尝试将LazySeq强制转换为IFn时出错

时间:2014-08-28 16:14:58

标签: clojure

刚开始学习100门问题的Clojure。我得到一个演员错误:

java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

这是我的代码:

(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)

2 个答案:

答案 0 :(得分:3)

请记住,Clojure会尝试执行它遇到的每个列表:

(+ 1 2)

此处符号+必须起作用,因此形式(+ 1 2)成功执行。即使引用也没有取消规则:

'(+ 1 2) => (quote (+ 1 2))

引用表单执行并返回其内容作为结果。因此,Clojure中每个列表的第一个元素必须是可执行的:符号绑定到宏或函数,或特殊运算符。

在您的示例中,我们看到:

(acc yy)

acc是一个懒惰的序列,(repeat n false)的结果。它无法执行,因此您会收到错误。

注意,函数中有一个递归调用,因此recur的参数是函数的参数。在Clojure函数的参数在使用之前得到评估。宏的参数没有。

答案 1 :(得分:0)

这是一个解决方案

(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))))))