31

Clojure 是一个函数式 lisp,据报道它根本不是面向对象的,尽管它运行在 JVM 上,JVM 是为面向对象语言设计的 VM。Clojure 通过将列表和向量抽象为一个名为 seq 的接口,为迭代列表和向量提供了相同的接口。这甚至使用称为 ISeq 的 Java 接口在内部实现。这不是面向对象抽象的例子吗?怎么能说 Clojure 不是面向对象的呢?

我想这个问题的一个推论——多态性何时可以被认为与面向对象不同?

4

4 回答 4

31

惯用的 Clojure 倾向于定义在非常小的核心数据结构集上运行的独立函数;这种方法和数据的分拆是反对面向对象并支持函数式风格的强烈声明。Rich Hickey(Clojure 的创建者)一再声明了这一点的重要性;例如这里:“Clojure 避开了为每种新情况创建新数据类型的传统面向对象方法,而是更喜欢在一小部分类型上构建大型函数库。” .

在 Clojure 中,对核心数据结构的依赖比在其他函数式语言中更为重要,因为只有在使用 Clojure 的持久数据结构时,您才能从 Clojure 的 STM 中获得全部好处。

我想这个问题的一个推论——多态性何时可以被认为与面向对象不同?

我正在使用 Clojure 的多方法(即多态工具)根据文件名的扩展名分派到不同的实现——根本不是面向对象的,而是多态的。

于 2009-10-10T16:59:55.637 回答
19

我想这个问题的一个推论——多态性何时可以被认为与面向对象不同?

多态性与面向对象完全没有关系。它只是意味着相同的操作可以根据其操作数的类型而表现不同。

像 ML 或 Haskell 这样的函数式语言已经有 30 多年的多态性,对 PL 历史有更深入了解的人可能会指出 1962 年之前(即 OO 之前)的一些例子。

Christopher Strachey 在 1967 年描述了参数多态性和 ad-hoc 多态性之间的区别,所以那时多态性一定已经存在。由于多态性仅在 Simula-67 中的 OO 中引入,我的猜测是多态性在 OO 中引入之前一定已经存在。

于 2009-10-10T20:59:15.013 回答
7

请记住,像 ISeq 这样的东西是 Java。

在 Clojure 中,seq 抽象实际上只是您可以提供给 first、rest 和 nth 函数的“东西”(请注意,您不会先在 seq 上调用,而是先使用 seq 参数调用)。Clojure 语言的核心函数都对集合、序列或原始类型进行操作。公开的接口中没有与方法绑定的数据。所以 Clojure 的实现是用 Java 实现的,所有与 JVM 的互操作都将涉及类/对象,但 Clojure 语言本身并不涉及。

Clojure 不鼓励将方法与数据结构捆绑在一起。

说了这么多……现实情况是,函数确实对它们将使用的参数有限制。first rest 和 nth 仅适用于可以是 seq 的东西。从这个角度来看,数据结构是否与方法捆绑并没有太大区别——您仍然必须正确匹配它们。最大的胜利来自灵活性。可以编写函数来接受任何参数,然后在不定义类等的情况下与高阶函数组合:

(def farms [{:name "Swansea", :value 100}
            {:name "Broadmarsh", :value 200, :produce [:corn :wheat :rye]}
            {:name "Snug", :value 50, :animals [:goats :pigs]}])
(reduce + (map :value farms))
-> 350
(reduce + (map :value (filter :animals farms)))
-> 50
于 2009-10-13T00:27:26.440 回答
4

Clojures 多态性是 Java 的自然扩展。在java中,方法是根据类分派的。在 clojure 中,这被扩展为允许您根据您想要的任何内容调度呼叫。它仍然很容易在课堂上调度,事实上大多数时候它就是这样完成的。如果你想要别的东西,那么你可以编写自己的调度程序。内置函数derive可根据您想要的任何内容创建层次结构,然后在isa.

更多优点:http: //clojure.org/multimethods

于 2009-10-12T20:18:51.673 回答