为什么clojure协议方法通常由函数包装?

为什么clojure协议方法通常由函数包装?,clojure,protocols,clojurescript,Clojure,Protocols,Clojurescript,通常,当我在库中看到clojure协议时,协议方法将被包装在一个函数中,通常很少添加功能。e、 g: (defprotocol Pfoo (foo-method [this])) (deftype Atype [x y] Pfoo (foo-method [this] (do-something))) (defn foo [arg] (foo-method arg)) 客户端通常需要调用函数foo,而不是协议中的foo方法。(有关这类事情的具体示例,请参见顶部的协议

通常,当我在库中看到clojure协议时,协议方法将被包装在一个函数中,通常很少添加功能。e、 g:

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

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

(defn foo [arg] (foo-method arg))
客户端通常需要调用函数foo,而不是协议中的foo方法。(有关这类事情的具体示例,请参见顶部的协议


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

协议代表两种具体实体之间的接口点。一种是调用协议的代码(在您的示例中,调用
foo
的任何东西),另一个是实现它的代码(
Atype
foo method
)。对一方方便的可能对另一方不方便。实现者希望提供最小的完整接口,而调用者希望能够支持最丰富的API

您提到了ClojureScript核心;看看那里的
ISeq
协议。它由几种类型实现,每种类型都必须实现
-first
-rest
。为了使这些尽可能容易实现,它们都不需要在其参数上调用seq。但是,相关函数
first
e> rest面调用方支持传入非序列,如字符串、向量等。因此,这一常见功能由非协议函数提供。当然,面向调用方的API甚至比
next
map
filter
、sequential destructuring等更加丰富,所有这些都是在
-first
之上构建的和
-rest

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