Clojure具有gen-class,reify,proxy以及deftype和defrecord来定义类新的数据类型。对于一种重视语法简单性并且讨厌不必要的复杂性的语言,这似乎是一种畸变。有人可以解释为什么会这样吗?普通的Lisp风格的defclass是否足够?
Answers:
这是三个不同因素的混合:
首先,让我们考虑一下这些功能。 deftype和gen-class相似之处在于,它们都为提前编译定义了一个命名类。Gen-class首先出现,其次是Clojure 1.2中的deftype。Deftype是首选,并且具有更好的性能特征,但限制性更强。deftype类可以符合接口,但不能从另一个类继承。
Reify和proxy都用于在运行时动态创建匿名类的实例。Proxy首先出现,Clojure 1.2中的deftype和defrecord伴随着reify。与deftype一样,在语义不太严格的情况下,最好使用Reify。
剩下的问题是,为什么deftype和defrecord会同时出现并起相似的作用。对于大多数目的,我们将要使用defrecord:它具有我们知道和喜欢的所有Clojure优点,可序列性等等。Deftype旨在用作实现其他数据结构的低级构建块。它不包括常规的clojure接口,但是它具有可变字段的选项(尽管这不是默认值)。
如需进一步阅读,请查看:
proxy
有时是首选,因为它允许在运行时修改方法。(例如,《 Clojure的欢乐》,第二版,建议您修改Web处理程序中的回调可能很方便。)
简短的答案是,它们都有不同的用途。复杂性是由于需要与底层JVM的不同功能进行有效互操作。
如果您不需要任何Java互操作,那么最好在99%的时间坚持使用defrecord或简单的Clojure映射。
如果您的需求更加复杂,那么以下流程图是一个很好的工具,用于解释为什么您会选择其中一个而不是其他选项:
http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/