2024 Clojure 状态调查!中分享您的想法。

欢迎!请参阅关于页面以获取更多关于如何使用此功能的信息。

0
记录与类型
  1. 我的项目依赖于“lib”库。
  2. 该库有一个协议lib.core/P包含10个函数和一个记录lib.core/R实施该协议。
  3. 在我的项目中,我需要一个记录my.core/Q类似于R:在10个函数中只有1个不同。

实现Q有哪些选择
a) 直接复制 R中的其他9个函数。
b) 还有什么其他方法?

是否有某种“记录优化”功能是有价值的?

(defrecord Q [a b c]
  :refines lib.core/R
  lib.core/P
  (just-my-one-changed-fn [] ...))

2 个回答

+1

选中
 
最佳答案

我认为由于对具体继承的哲学反对,将“优化”视为增强的可能性相当低。

一种处理方法是让R和Q的impls调用同一个函数。另一种方法是利用协议的底层实现功能来外部提供处理过的扩展。

协议的一个重要优点是可以外部扩展,超出类型。协议实际上只是包含类型到函数impls映射的映射。您可以为拉取基impls、进行优化并添加到协议映射的方法定义一个优化宏。这可能有些复杂,我无法详细说明,但是是可能的。

您还可以使用多方法以及关键字层次结构支持作为另一种选择(但缺点是需要10个或更多多方法)。

+1

也许你可以让“Q具有R”。在这种情况下,你的工作差不多完成了。

也许你需要分叉库来实现你需要的(或者更容易扩展)。

你可以在Datatypes页面上找到Clojure放弃实现继承的部分理由:[https://clojure.org/reference/datatypes#_datatypes_and_protocols_are_opinionated](https://clojure.org/reference/datatypes#_datatypes_and_protocols_are_opinionated)

"Q has-an R" `(defrecord Q [r]` 组合确实可以避免复制粘贴,但是我还必须定义Q中的所有其他9个函数以及r字段的代理调用;并且,从行为的角度来看,并不总是可行,例如
- 例如,`(f r)` 调用 `(my-one-fn r)`
- 以及,`(f q)` 通过 `(f r)`
- 其中调用 `(my-one-fn r)` 而不是 `(my-one-changed-fn q)`
这是预期的行为。

无论如何,这样的提及都受到欢迎!

编辑
我之所以使用“精炼”这个词,是因为“具体派生是坏”那一备注。结果可以是复制覆盖的实现,而不是派生。
...