Clojure具有gen-class,reify,proxy以及deftype和defrecord来定义新的类类数据类型。对于一种重视句法简洁性并憎恶不必要的复杂性的语言来说,这似乎是一种失常。 有人可以解释为什么会这样吗? Common Lisp风格的defclass能够满足吗?
答案 0 :(得分:87)
这是三个不同因素的混合:
首先,让我们考虑一下这些。 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地图。
如果您的需求更复杂,那么以下流程图是一个很好的工具,可以解释为什么您会选择其中一个选项而不是其他选项:
http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/