【问题标题】:Why does Clojure have 5 ways to define a class instead of just one?为什么 Clojure 有 5 种方法来定义一个类而不是只有一种?
【发布时间】:2011-10-31 19:58:52
【问题描述】:

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

【问题讨论】:

    标签: clojure clojure-java-interop


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 非常感谢流程图的链接。该博客由 O'reilly 的 - Programming Clojure 的合著者撰写,这很有帮助。我认为这个决策是相当复杂的。接口和具体类之间的差异,或者是否需要定义静态方法,或者命名类型或匿名类型之间的差异如此之大,以至于它们需要不同的语言结构?
    • 差异并不大,但就您要达到的目标而言,它们在哲学上有所不同。我认为 Clojure 中的多种方法反映了这些潜在的差异,这就是为什么它们应该被赋予不同名称的一个很好的理由。
    • 流程图很棒,但并未涵盖使用一个或另一个选项或它们的组合的所有可能性或原因。没有简单的图表可以。
    【解决方案2】:

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

    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 接口,但它确实具有可变字段的选项(尽管这不是默认值)。

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

    The clojure.org datatypes page

    The google group thread where deftype and reify were introduced

    【讨论】:

    • google 群组线程非常有价值。我的理解是对于 java-interop 代理,gen-class 主要被 reify 和 deftype 所取代。我很高兴我们现在有更少的“推荐”方式来定义类型。
    • @Trylks :将对象视为键值对序列的能力。 clojure 原生的几乎所有东西都可以被视为一个序列,这是非常强大的。
    • proxy 有时是首选,因为它允许在运行时修改方法。 (例如,The Joy of Clojure,第 2 版。建议这对于修改 Web 处理程序中的回调可能很方便。)
    猜你喜欢
    • 2013-04-20
    • 2014-02-04
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多