2017-12-17 11 views
1

Clojureで簡単な推測ゲームを書こうと思っていましたが、このエラーが発生しました。私は、私の中の関数のように扱われるCharacterはどこにあるのかわかりません。その結果、そのような問題はないはずです。ここでは、コードです:Clojure:java.lang.Characterをclojure.lang.IFnにキャストすることはできません

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

マイ入力された:\ bの\ \ hを

答えて

2

エラーのように文字を評価しようとしてから来ていますこの関数は、例えば:

(\a) => Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Character cannot be cast to clojure.lang.IFn, 

私はそれがif文の中の余分な括弧であると思います文字を関数として評価しようとする。 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> 
() 

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 

だからあなたは()(引用符で囲まれていない)を使用することができ、空のリストについては、(私は忘れてしまった:count機能を使う

、あなたが問題を見ることができます)、あなたがそれを引用しない限り空でなければ失敗します。ベクトルを使用する方が簡単でエラーが発生しにくいです。

demo.core=> (count []) 
0 
demo.core=> (count [\b]) 
1 
demo.core=> (count [1]) 
1 
+0

私は、エラーメッセージが何を意味するか知っている、私は知りません間違い。出力から見ることができるように、それでも空のリストを出力して失敗します。これは絶対に意味がありません。ところで、この()のような空のリストに何が間違っているのでしょうか? –

+0

元のコードの空の括弧が、新しいバージョンのコードで '(let ...)'形式に置き換えられたことに注意してください。空の括弧が例外の原因でした。 –

+0

さて、私は引用符で囲まれていない空リストをすべて引用符で囲んだものに置き換えました。ベクターも試しましたが、同じエラーが出ます。 –

1

文字を関数として評価しようとしています。コードにevalを使用しないでください。代わりに、read機能から来たシンボルのリストを操作してください。それはユーザーの入力を評価するよりはるかに安全です。

defを関数の内部では使用しないでください。モジュールの上部でのみ使用してください。 Defは、名前空間全体の中で新しいエンティティをグローバルに宣言します。 letフォームを使用して、評価が存在するまでその変数が存在するローカルスコープを作成します。

また、関数自体が再帰的に呼び出されます。これは短いゲームセッションでは問題ありませんが、長いセッションではトラブルが発生する可能性があります。あなたはrecurフォームで内部呼び出しを置き換えることができるようにあなたのケースでは、機能akasztofa!は末尾再帰の最適化基準(TRO)をフィット:私が作ったところ

(recur (removeEach s guess) lives) 
(recur s (- lives 1)))) 
関連する問題