我只想在Clojure中编写一个简单的小猜谜游戏,我收到了这个错误。我无法看到Character在哪里被视为我的函数,因为结果输入也预测不应该存在这样的问题。这是代码:
(ns clojure.examples.hello
(:gen-class))
(ns clojure-noob.core)
(defn takeFst [x n]
(if (= n 0) () (cons (first x) (takeFst (rest x) (- n 1))))
)
(defn createSeq [elem n]
(if (= n 0) () (cons elem (createSeq elem (- n 1))))
)
(defn fnEquals? [n]
(fn [elem] (= elem n))
)
(defn removeEach [x elem]
(remove (fnEquals? elem) x)
)
(defn containsString? [s ch]
(not (empty? (filter true? (map = (createSeq ch (count s)) s))))
)
(defn akasztofa! [s lives]
(println s)
(if (and (not= () s) (not= lives 0))
(
(def guess (eval (read)))
(if (containsString? s guess) (akasztofa! (removeEach s guess) lives) (akasztofa! s (- lives 1)))
)
()
)
)
(akasztofa! "hab" 10)
我得到的输出是:
hab
(a b)
(b)
()
Exception in thread "main" java.lang.ClassCastException:
java.lang.Character cannot be cast to clojure.lang.IFn, compiling:
(/home/cicaharcos/Documents/Clojure/First/akasztofa/main.clj:38:1)
我的输入是:\ h \ a \ b
答案 0 :(得分:2)
错误来自于尝试将角色评估为函数,例如:
(\a) => Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Character cannot be cast to clojure.lang.IFn,
我认为if
语句中的额外parens试图将角色评估为函数。请记住,在Clojure中,括号不是"分组"就像在Java中一样,它们意味着"函数调用"。
您的代码还有其他一些问题,值得注意的是使用()
作为空列表。您必须像这样引用列表:
'()
或者,更好的是,使用带方括号的空向量(不需要引用):
[]
如果您使代码看起来如下所示,它似乎有效:
(ns clojure.examples.hello
(:gen-class))
(ns clojure-noob.core)
(defn takeFst [x n]
(if (= n 0) [] (cons (first x) (takeFst (rest x) (- n 1))))
)
(defn createSeq [elem n]
(if (= n 0) [] (cons elem (createSeq elem (- n 1))))
)
(defn fnEquals? [n]
(fn [elem] (= elem n))
)
(defn removeEach [x elem]
(remove (fnEquals? elem) x)
)
(defn containsString? [s ch]
(not (empty? (filter true? (map = (createSeq ch (count s)) s))))
)
(defn akasztofa! [s lives]
(println s)
(if (and (not= [] s) (not= lives 0))
(let [guess (eval (read))]
(if (containsString? s guess)
(akasztofa! (removeEach s guess) lives)
(akasztofa! s (- lives 1))))
[] ))
(akasztofa! "hab" 10)
结果:
hab
\h ; <= user input plus <ret>
(a b)
\a ; <= user input plus <ret>
(b)
\b ; <= user input plus <ret>
()
使用count
功能,您可以看到问题:
demo.core=> (count ())
0
demo.core=> (count (\b))
ClassCastException java.base/java.lang.Character cannot be cast to clojure.lang.IFn demo.core/eval16682 (form-init2403719904611886388.clj:1)
demo.core=> (count (1))
ClassCastException java.base/java.lang.Long cannot be cast to clojure.lang.IFn demo.core/eval16686 (form-init2403719904611886388.clj:1)
demo.core=> (count '(\b))
1
所以你可以使用()
(不带引号)作为一个空列表(我忘记了),但如果它是非空的,它会失败,除非你引用它。使用向量更简单,更不容易出错:
demo.core=> (count [])
0
demo.core=> (count [\b])
1
demo.core=> (count [1])
1
答案 1 :(得分:2)
您正在尝试将角色评估为函数。您应该避免在代码中使用eval
。相反,使用来自read
函数的符号列表。这比评估用户的输入要安全得多。
不要在函数内部使用def
,只能在模块顶部使用Def
。 let
在整个命名空间中全局声明一个新实体。使用akasztofa!
形式创建一个本地范围,其变量存在,直到评估存在。
此外,您的函数以递归方式调用自身。对于短暂的比赛来说,这是好的,但可能会导致长期比赛的麻烦。在您的情况下,函数recur
符合尾递归优化标准(TRO),以便您可以用(recur (removeEach s guess) lives)
(recur s (- lives 1))))
形式替换内部调用:
Promise.catch