Clojure定义多方法以及如何传递参数

sip*_*r92 1 clojure multimethod

我似乎很难理解下面的代码是如何工作的.更准确地说,定义的函数如何处理传递的参数

(defmulti encounter
    (fn [x y] [(:role x) (:role y)]))

(defmethod encounter [:manager :boss] [x y]
    :promise-unrealistic-deadlines)

(defmethod encounter [:manager :developer] [x y]
    :demand-overtime)
....
Run Code Online (Sandbox Code Playgroud)

为什么[x y] [(:role x) (:role y)]在定义"遇到"时我们有2个向量().这是否意味着函数采用向量参数?如果是这样,为什么我必须调用这样的函数:

(encounter {:role :manager} {:role :boss})

上面的调用不是将第一个hashmap传递给[xy]而第二个传递给[(:role x)(:role y)]).我只是无法理解x如何得到值:经理和y得到的价值:老板.

上面的例子来自这里:https://yogthos.github.io/ClojureDistilled.html

小智 5

传递给defmulti宏的第二个参数称为调度函数.在这里,它接受两个参数,x并且y每个参数都应该是一个带有:role键的映射.dispatch函数返回的值称为dispatch值.无论何时打电话都会与之进行比较encounter.

encounter方法的每个定义都将一些调度值作为其第二个参数.在你的榜样,该值是通过传递参数产生xy进入调度功能(fn [x y] [(:role x) (:role y)])里面defmulti.根据该函数返回的值,可以调用相应的方法,也IllegalArgumentException可以抛出a:

(encounter {:role :designer} {:role :developer})
Run Code Online (Sandbox Code Playgroud)

产生

IllegalArgumentException No method in multimethod 'encounter' for dispatch value: [:designer :developer]  clojure.lang.MultiFn.getFn (MultiFn.java:156)
Run Code Online (Sandbox Code Playgroud)

但是添加一个新的可能的调度值可以修复它:

(defmethod encounter [:designer :developer] [x y]
  :discuss-video-games)

(encounter {:role :designer} {:role :developer})
=> :discuss-video-games
Run Code Online (Sandbox Code Playgroud)

还有一个专门的clojuredocs页面,里面有更好的例子.