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

欢迎!有关此工作方式的更多信息,请查看关于页面。

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

实现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的实现中调用同一个函数。另一种方法是使用协议较低级别的实现功能来外部提供修改后的扩展。

协议的一个大优点是它们可以在类型外部扩展。协议实际上只是包含类型到函数实现的映射的映射。您可以定义一个精炼宏,该宏展开为提取基本实现,应用修改,并添加那些方法到协议映射中。这对我来说可能有点复杂,但它是可能的。

您还可以使用多方法并支持关键词层次作为另一个选项(缺点是需要10个或更多多方法)。

+1

或许你可以让它成为“Q具有R”。在这种情况下,你的工作几乎就完成了。

也许你需要分叉库来使其执行你需要的操作(或者更容易扩展)。

你可以在数据的类型页面上找到Clojure排除实现继承的理据: 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)`
这正是预期的行为。

无论如何,提到的内容受到了热烈的欢迎!

编辑
我使用“细化”这个词,因为“具体派生是坏的”的注释。结果可以是复制-over-实现,不一定是派生。
...