2013-03-28 51 views
14

通常,当我在库中看到clojure协议时,协议方法将被包装在一个函数中,通常很少添加功能。例如:为什么clojure协议方法经常被函数包装?

(defprotocol Pfoo 
    (foo-method [this])) 

(deftype Atype [x y] 
    Pfoo 
    (foo-method [this] (do-something))) 

(defn foo [arg] (foo-method arg)) 

而且客户端通常需要调用函数foo,而不是协议中的foo-method。 (请参阅clojurescript core顶部的协议以了解此类事物的具体示例。

那么为什么协议经常被掩盖在函数后面?难道协议方法不能成为面向客户端的部分,而不是包装函数?

回答

22

协议代表的接口点两种混凝土实体之间,一个是调用协议(任何在您的示例调用foo)的代码,另一种是在代码执行它(Atypefoo-method)什么是方便一个可能对另一方来说不方便,实现者希望提供完整的最小接口,而呼叫者需要可以支持的最丰富的API。

你提到过ClojureScript核心;看看那里的ISeq协议。它由几种类型实现,每种类型必须实现-first-rest。为了使这些尽可能简单到实现,无需在其arg上调用seq。但是,面向调用者的相关函数firstrest支持传入非seqs,如字符串,向量等,因此这种通用功能由非协议函数提供。当然,面向调用者的API甚至比next,map,filter,顺序解构等均建立在-first-rest之上。

包装协议方法的fns提供的其他常见功能包括参数验证(如断言),默认参数和对var-args的支持。

+0

另请参阅http://www.gotw.ca/publications/mill18.htm – Chouser 2013-05-13 13:27:55