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

发布于 2024-11-30 14:29:55 字数 157 浏览 4 评论 0原文

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

Clojure has gen-class, reify, proxy and also deftype and defrecord to define new class-like datatypes. For a language that values syntactic simplicity and abhors unnecessary complexity, it seems like an aberration.
Could someone explain why it is so? Could Common Lisp-style defclass have sufficed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

§对你不离不弃 2024-12-07 14:29:55

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

  1. jvm 的特定类型系统
  2. 定义类型时不同用例需要稍微不同的语义 事实上,随着
  3. 语言的发展,其中一些是较早开发的,有些是较晚开发的。

首先,让我们考虑一下它们的作用。 deftypegen-class 的相似之处在于,它们都为提前编译定义了一个命名类。在 clojure 1.2 中,Gen-class 排在第一位,其次是 deftype。 Deftype 是首选,并且具有更好的性能特征,但限制更多。 deftype 类可以符合接口,但不能从另一个类继承。

Reifyproxy都用于在运行时动态创建匿名类的实例。 Proxy 首先出现,reify 在 clojure 1.2 中与 deftype 和 defrecord 一起出现。 Reify 是首选,就像 deftype 一样,语义没有太大限制。

这就留下了一个问题:为什么 deftype 和 defrecord 是同时出现的,并且具有相似的作用。对于大多数目的,我们会想要使用 defrecord:它具有我们所了解和喜爱的所有 clojure 优点、可排序性等等。 Deftype 旨在用作实现其他数据结构的低级构建块。它不包括常规的 clojure 接口,但它确实具有可变字段的选项(尽管这不是默认值)。

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

clojure.org 数据类型页面

引入 deftype 和 reify 的 Google 群组线程

This is a mix of three different factors:

  1. The particular type system of the jvm
  2. The need for slightly different semantics for different use cases when defining types
  3. The fact that some of these were developed earlier, and some later, as the language has evolved.

So first, let's consider what these do. deftype and gen-class are similar in that they both define a named class for ahead-of-time compilation. Gen-class came first, followed by deftype in clojure 1.2. Deftype is preferred, and has better performance characteristics, but is more restrictive. A deftype class can conform to an interface, but cannot inherit from another class.

Reify and proxy are both used to dynamically create an instance of an anonymous class at runtime. Proxy came first, reify came along with deftype and defrecord in clojure 1.2. Reify is preferred, just as deftype is, where the semantics are not too restrictive.

That leaves the question of why both deftype and defrecord, since they appeared at the same time, and have a similar role. For most purposes, we will want to use defrecord: it has all the various clojure goodness that we know and love, sequability and so forth. Deftype is intended for use as a low level building block for the implementation of other datastructures. It doesn't include the regular clojure interfaces, but it does have the option of mutable fields (though this isn't the default).

For further reading check out:

The clojure.org datatypes page

The google group thread where deftype and reify were introduced

梦屿孤独相伴 2024-12-07 14:29:55

简而言之,它们都有不同且有用的目的。其复杂性是由于需要与底层 JVM 的不同功能进行有效的互操作。

如果您不需要任何 Java 互操作,那么 99% 的情况下您最好坚持使用 defrecord 或简单的 Clojure 映射。

  • 如果您想使用协议,请使用 defrecord
  • 否则,常规 Clojure 映射可能是最简单且最容易理解的。

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

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

选择流程图右 clojure 类型定义形式

The short answer is that they all have different and useful purposes. The complexity is due to the need to interoperate effectively with different features of the underlying JVM.

If you don't need any Java interop then 99% of the time you are best off sticking with either defrecord or a simple Clojure map.

  • Use defrecord if you want to use protocols
  • Otherwise a regular Clojure map is probably simplest and most understandable

If your needs are more complex, then the following flowchart is a great tool for explaining why you would choose one of these options over the others:

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

Flowchart for choosing the right clojure type definition form

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文