2011-12-17 8 views
4

defmultiとdefmethodについて重要な点がありません。私はdefmultiのいくつかの本の説明を読んだが、私はまだ混乱している。Clojure defmulti/defmethodの作成

私はそれがトランザクションまたは私は(ランダム-VAL)を呼び出すと、どちらかの役に立つ-transの値またはランダム小数量を取り戻すしたい100.00

ような量だかどうかに応じて、ランダムな値を取得したいです。私は地図に関数を入れて実験しましたが、avail-trans、\ Bと同じ値を返します。

(def^:dynamic map-val {:trans (random-trans) :amt (random-amount)}) 

ここでは、私がやっていることが動作していないことを示す最小のコードです。私は指針や助けに感謝します。

(def^:dynamic avail-trans [\B \W \D \A]) 

(defn random-trans 
    [] 
    (nth avail-trans (.nextInt random (count avail-trans)))) 

(defn random-amount 
    [] 
    (float (/ (.nextInt random (count (range 1 10000))) 25))) 

次は、正しく構築されていませんが、私はよく分からない理由や問題解決方法:

(defmulti random-val :val-type) 

(defmethod random-val :trans [] 
    (random-trans)) 

(defmethod random-val :amt [] 
    (random-amount)) 

このエラーで(random-val :trans)結果の呼び出し:

れるjava.langを。 IllegalArgumentException:ディスパッチ値のマルチメソッド 'random-val'のメソッドがありません:null(NO_SOURCE_FILE:0)

答えて

7

マルチメソッドがで作成されています;あなたはそうしています。 defmultiには、名前とディスパッチ関数(そしてdocstringといくつかのオプションが必要ですが、それらについては忘れてください)が必要です。

(defmulti random-val identity) 

あなたはdefmethodとmultimethodを実装する場合、あなたはそれがやりたいものは何でもあなたが実装しようとしているmultimethod、それが一致する必要がありディスパッチ値、およびその関数のテール(引数リストプラスの名前を指定する必要があります)。

(defmethod random-val :trans [t] (random-trans)) 
(defmethod random-val :amt [t] (random-amt)) 

あなたがrandom-valを割り当てられたディスパッチ機能、:val-typeは、他のキーワードに適用した場合、それはあなたのnullを与えるので、あなたはjava.lang.IllegalArgumentException: No method in multimethod 'random-val' for dispatch value: null (NO_SOURCE_FILE:0)を取得しています。 Clojureがそのディスパッチ値と一致するメソッドを検索しようとすると失敗します。

しかし、そこで失敗しなかったとしても、定義されたメソッドは0の値を取るので、それも修正する必要があります(上記のように)。

最後に、これはプロトコルのための良い使用のようには思われません。あなたの2つの別個の機能、random-amountrandom-transを使用してください。

Clojure's websiteには、マルチメソッドの説明があります。

+1

私は非常に多くの答えを感謝しています。 ClojureのWebサイトで見た2つの答え(これまでのところ)は、私が見たよりも優れています。賢明な男は意図していませんでしたが、Clojureは私には「村に行く」という言語/学習体験のひとつと思われます。私はすべての答えを聞いて何かを得る。 – octopusgrabbus

+0

私はこの特定の例をマルチメソッドに使用しないように納得しましたが、あなたが示したように私の例を並べ替えると、私はそれをどのように呼び出すでしょうか? – octopusgrabbus

+0

あなたが何を求めているのかよく分かりません。マルチメソッドを使いたければどうしますか?上に書いたコードはあなたが意図したとおりに動作するはずです。 – Isaac

1

あなたが戻っ役に立つトランスのため毎回同じ値を取得する「\B」あなたはあなたのマップmap-valでそれを関連付けるときには、このように、キーに対して永遠値Bを結合、機能を評価しているので、「:トランス」MAP-でvalの代わりに、関数randon-transの代わりに。

map-valで関数の割り当てを囲む括弧を削除するとうまくいきます。それでは、@ isaac-hodesが示唆しているように、おそらく適切でないマルチメソッドの必要はありません。

これはREPLで私の作品:

(def avail-trans [\B \W \D \A]) 
(def random (java.util.Random.)) 

(defn random-trans [] 
    (nth avail-trans (.nextInt random (count avail-trans)))) 

(defn random-amount [] 
    (float (/ (.nextInt random (count (range 1 10000))) 25))) 

; No parens around function names 
(def map-val {:trans random-trans :amt random-amount}) 

(println ((:trans map-val))) 
(println ((:amt map-val))) 
+0

ありがとう、これは役に立ちました。私は元気で何がうまくいかないのかを平和にしようとしていました。 – octopusgrabbus

関連する問題