构造Clojure defmulti/defmethod

oct*_*bus 4 clojure

我错过了关于defmulti和defmethod的重要观点.我读过几本书对defmulti的解释,我仍然感到困惑.

我想得到一个随机值,取决于它是一个交易还是100.00这样的金额

我想调用(random-val)并返回avail-trans值或随机小数.我已经尝试将函数放在一个映射中,但是我得到了相同的值,用于avail-trans,一个\ B.

(def^:dynamic map-val {:trans (random-trans) :amt (random-amount)})
Run Code Online (Sandbox Code Playgroud)

这是显示我正在做的不起作用的最小代码量.我很感激任何指针或帮助.

(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 )))
Run Code Online (Sandbox Code Playgroud)

以下构造不正确,但我不确定为什么或如何解决问题:

(defmulti random-val :val-type)

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

(defmethod random-val :amt []
    (random-amount))
Run Code Online (Sandbox Code Playgroud)

调用(random-val :trans)导致此错误:

java.lang.IllegalArgumentException:multimethod'random-val'中没有用于调度值的方法:null(NO_SOURCE_FILE:0)

Isa*_*aac 7

创建一个多方法defmulti; 你这样做了.defmulti需要一个名称和一个调度函数(和一个文档字符串,加上一些选项,如果你愿意,但忘了那些).

(defmulti random-val identity) 
Run Code Online (Sandbox Code Playgroud)

当你使用multi方法实现时defmethod,你需要指定你正在实现的多方法的名称,它应该匹配的调度值,然后是函数tail(arglist加上你想要它做的任何事情).

(defmethod random-val :trans [t] (random-trans))
(defmethod random-val :amt [t] (random-amt))
Run Code Online (Sandbox Code Playgroud)

你得到java.lang.IllegalArgumentException: No method in multimethod 'random-val' for dispatch value: null (NO_SOURCE_FILE:0),因为当你分配的调度功能random-val,:val-type适用于任何其他的关键词,它给你null.当Clojure试图查找匹配该调度值的方法时,它会失败.

但即使它没有在那里失败,你定义的方法也有0个arity(没有值),所以你也需要修复它(在上面完成).

最后,这似乎不是一个很好的协议使用.只需使用你的两个独立功能,random-amountrandom-trans.

请注意,Clojure的网站对多方法有很好的解释.