Clojure defmethod & defmulti

defmethod
(defmethod multifn dispatch-val & fn-tail)
创建并安装一个关联dispatch值的multimethod。
 
multifn  指定需要创建并安装的multimethod名称,该名称与defmulti的名称一致。
dispatch-val  指定一个关联的dispatch value
&  这个符号好像可有可无
fn-tail  multimethod函数尾,正常的函数定义为:
(fn name? [params*] exprs*)
(fn name? ([params*] exprs*) +)
这里的multimethod函数尾为函数名后面的那一部分。
 
我们在使用 defmulti 创建multimethod的时候需要指定一个关联的dispatch function,在使用 defmethod创建multimethod的时候需要指定一个关联的dispatch value 
这里有几个概念需要清楚:
dispatch function
dispatch value
在使用 defmulti 创建multimethod的时候指定关联的dispatch function用于做转发函数,通过对这个转发函数求值后跟 defmethod中关联的dispatch值进行匹配
 
完整例子可参考 defmulti后面的例子。
 
 
<!--[if ppt]-->
defmulti
(defmulti name docstring? attr-map? dispatch-fn & options)
创建一个关联 dispatch 函数的 multimethod.
 
docstring, attr-map 是可选的
options 可以是 key-value 对,或者是以下其中一个:
:default   默认的 dispatch
:hierarchy 用于继承层次的 dispatch( 例如 ::square is-a( ) ::shape)
 
例如:
user=> (defmulti greeting
  #_=>   (fn[x] (x "language")))
Nil
user=> (defmethod greeting "English" [params]
  #_=>   (str params (class params) "Hello!"))
#object[clojure.lang.MultiFn 0x4054c9a3 "clojure.lang.MultiFn@4054c9a3"]
user=> (defmethod greeting "French" [params]
  #_=>   (str params (class params) "Bonjour!"))
#object[clojure.lang.MultiFn 0x4054c9a3 "clojure.lang.MultiFn@4054c9a3"]
user=> (defmethod greeting :default [params]
  #_=>   (throw (IllegalArgumentException.
  #_=>     (str params (class params) "I don't know the " (params "language") " language"))))
#object[clojure.lang.MultiFn 0x4054c9a3 "clojure.lang.MultiFn@4054c9a3"]
user=> (def english-map {"id" "1", "language" "English"})
#'user/english-map
user=> (def  french-map {"id" "2", "language" "French"})
#'user/french-map
user=> (def spanish-map {"id" "3", "language" "Spanish"})
#'user/spanish-map
user=> (greeting english-map)
"{\"id\" \"1\", \"language\" \"English\"}class clojure.lang.PersistentArrayMapHello!"
user=> (greeting french-map)
"{\"id\" \"2\", \"language\" \"French\"}class clojure.lang.PersistentArrayMapBonjour!"
user=> (greeting spanish-map)
IllegalArgumentException {"id" "3", "language" "Spanish"}class clojure.lang.PersistentArrayMapI don't know the Spanish language  user/eval1431/fn--1432 (form-init5755127293752614979.clj:3)
 
 
一个实际的例子:
这里定义了一个函数 executor-selector
( defn executor-selector [executor-data & _] (:type executor-data))
 
 
这里创建了一个关联 executor-selector dispatch 数的 multimethod
(defmulti mk-threads executor-selector)
 
这里创建并安装了一个关联 :spout 
dispatch 值的 multimethod 
 
 


 
这里创建并安装了一个关联 :bolt
dispatch 值的 multimethod 
 


 
最后在这里进行求值: 
(mk-threads executor-data task-datas initial- credentials)
 
 
 
<!--[if ppt]--> <!--[endif]-->
 
 
 
 
 
 

猜你喜欢

转载自lobin.iteye.com/blog/2326240