为什么Clojure有五种方法来定义一个类而不是一个类?

Clojure具有gen-class,reify,proxy,deftype和defrecord来定义新类types的数据types。 对于语法简单并且不必要的复杂的语言来说,这似乎是一种失常。 有人能解释为什么是这样吗? Common Lisp风格的defclass能够吗?

这是三个不同因素的混合:

  1. jvm的特定types系统
  2. 定义types时,需要针对不同用例略有不同的语义
  3. 事实上,其中一些是随着语言的发展而发展起来的。

首先,我们来看看这些做什么。 deftypegen-class是相似的,它们都为提前编译定义了一个命名类。 Gen-class是第一个,接下来是clojure中的deftype 1.2。 Deftype是优选的,并且具有更好的性能特征,但是更具限制性。 deftype类可以符合一个接口,但不能从另一个类inheritance。

ReifyProxy都用于在运行时dynamic创build一个匿名类的实例。 代理来了第一,在clojure 1.2 reify与deftype和defrecord一起来了。 Reify是优选的,就像deftype一样,语义不是太严格。

这就产生了这样的问题:既然它们同时出现,并且具有类似的作用,那么为什么既定型又定义了折旧。 对于大多数目的,我们将要使用defrecord:它具有我们所知道和喜爱的所有各种clojure善良,sequability等等。 Deftype旨在用作实现其他数据结构的低级构build块。 它不包括常规的clojure接口,但它有可变字段的选项(虽然这不是默认的)。

为进一步阅读检查:

clojure.org数据types页面

引入了deftype和reify的google组线程

简短的回答是,他们都有不同的和有用的目的。 复杂性是由于需要与底层JVM的不同function进行有效的互操作。

如果你不需要任何Java互操作,那么99%的时间你最好坚持defrecord或简单的Clojure地图。

  • 如果你想使用协议,使用defrecord
  • 否则,一个普通的Clojure地图可能是最简单也是最容易理解的

如果您的需求更复杂,那么下面的stream程图就是解释为什么您会select其中一个选项的一个很好的工具:

http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

选择正确的clojure类型定义表单的流程图