Clojure 中有没有办法使协议(或其他类型结构)对扩展关闭?

Is there a way in Clojure to make a protocol (or other type structure) closed to extension?

在 Clojure 中我们有多种扩展机制:extend-type, extend-protocol, extend.

现在我们做一些假设:

这个问题有一些背景。 Philip Wadler 谈论 the expression problem. This discussion is expanded here 因为它与 代数数据类型 :

相关

With algebraic data types,

It is very cheap to add a new operation on things: you just define a new function. All the old functions on those things continue to work unchanged.

It is very expensive to add a new kind of thing: you have to add a new constructor an existing data type, and you have to edit and recompile every function which uses that type.

With classes,

It is very cheap to add a new kind of thing: just add a new subclass, and as needed you define specialized methods, in that class, for all the existing operations. The superclass and all the other subclasses continue to work unchanged.

It is very expensive to add a new operation on things: you have to add a new method declaration to the superclass and potentially add a method definition to every existing subclass. In practice, the burden varies depending on the method.

现在这背后的驱动力(他们是从 Haskell 的角度来看)是函数式编程中的一个概念,称为 total functions. (This is related to parametricity in functional programming). The benefit 总函数 是编写的程序可证明终止

现在这似乎是计算机科学的一项微不足道的好处 - 但它对 Clojure 世界中的我们来说确实有好处。喜欢 Steve Miner and Reid Draper are working on simple-check 的人。现在,如果我们有一个 总函数 那么我们可以确信给定一个输入域,我们可以保证输出的范围。

现在,如果您可以将类型关闭到扩展,则可以更轻松地声明函数 'total function' - 并使简单检查等工具的工作更轻松、更全面。 (并且更有信心一个函数会按照它所说的去做)。

现在看来Ambrose' work on core.typed is starting to approach这个目标。

所以我的问题是:Clojure 中有没有办法使协议(或其他类型结构)对扩展关闭? (或者这完全是非惯用语?)

reify 创建对象会给你一个匿名类型的对象。由于该类型是匿名的,因此无法将其扩展到任何其他协议。但这只是一方面;它不会阻止其他人将 reify 主体中的协议扩展到 other types/records.

我认为没有任何方法可以通过记录、类型或协议来实现这一点(除非深入研究底层实现)。