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

时间:2011-08-22 02:03:25

标签: clojure clojure-java-interop

Clojure具有gen-class,reify,proxy以及deftype和defrecord来定义新的类类数据类型。对于一种重视句法简洁性并憎恶不必要的复杂性的语言来说,这似乎是一种失常。 有人可以解释为什么会这样吗? Common Lisp风格的defclass能够满足吗?

2 个答案:

答案 0 :(得分:87)

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

  1. jvm的特定类型系统
  2. 定义类型
  3. 时,对不同用例需要稍微不同的语义
  4. 随着语言的发展,其中一些是早期开发的,有些是后来开发的。
  5. 首先,让我们考虑一下这些。 deftype gen-class 类似,因为它们都定义了一个用于提前编译的命名类。 Gen-class排在第一位,然后是clojure 1.2中的deftype。 Deftype是优选的,并且具有更好的性能特征,但是更具限制性。 deftype类可以符合接口,但不能从其他类继承。

    Reify 代理都用于在运行时动态创建匿名类的实例。代理首先出现,reify与clojure 1.2中的deftype和defrecord一起出现。 Reify是首选,就像deftype一样,语义不是太严格。

    这就留下了为什么deftype和defrecord都出现的问题,因为它们同时出现,并且具有相似的作用。在大多数情况下,我们会想要使用defrecord:它具有我们所知道和喜爱的各种各样的clojure善良,sequability等等。 Deftype旨在用作实现其他数据结构的低级构建块。它不包括常规的clojure接口,但它确实有可变字段的选项(虽然这不是默认的)。

    如需进一步阅读,请查看:

    The clojure.org datatypes page

    The google group thread where deftype and reify were introduced

答案 1 :(得分:49)

简短的回答是,它们都有不同的用途。复杂性是由于需要与底层JVM的不同功能进行有效互操作。

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

  • 如果要使用协议,请使用defrecord
  • 否则,常规的Clojure地图可能是最简单且最容易理解的

如果您的需求更复杂,那么以下流程图是一个很好的工具,可以解释为什么您会选择其中一个选项而不是其他选项:

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

Flowchart for choosing the right clojure type definition form