2016-03-16 32 views
1

我似乎很难理解下面的代码是如何工作的。更确切地说,是如何定义的函数处理传递的参数定义的“遭遇”时Clojure定义多方法以及如何传递参数

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

为什么我们有2个向量([x y] [(:role x) (:role y)])。这是否意味着函数需要向量参数?如果是这样,为什么我要调用的功能等:

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

不是上述呼叫经过第一HashMap来[xy]或第二至[(:角色X)(:角色Y) ])。我只是不明白如何x得到价值:经理和y得到的价值:老板。

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

回答

5

传递给defmulti宏的第二个参数被称为调度功能。在这里,它接受两个参数,xy,其中每个参数预计都是带有:role键的地图。调度函数返回的值称为调度值。正在与您拨打encounter时进行比较。

encounter方法的每个定义都将一些分派值作为其第二个参数。在您的示例中,该值是通过将参数xy传递到defmulti内的调度函数(fn [x y] [(:role x) (:role y)])中生成的。根据由该函数返回的值,或者是相应的方法被调用,或IllegalArgumentException抛出:

(encounter {:role :designer} {:role :developer}) 

产生

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

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

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

(encounter {:role :designer} {:role :developer}) 
=> :discuss-video-games 

还有一个dedicated clojuredocs page更多的好例子。