在clojure中,是(='a'a)指的是'同一个原子'?

时间:2010-09-07 08:43:53

标签: java clojure lisp scheme

在Common LISP的一些实现中,我们可以说对于以下表达式

(eq 'a 'a)

true,因为'a'a是“相同的原子”。

这可能是依赖于实现的,但似乎短语(在流行的LISP教学书中使用)假设相同值的原子存储在内存中的相同位置。

在Java中,两个具有相同值的实习字符串存储在内存中的相同位置。

现在JVM上的Clojure继承了Java的遗产,但是说Clojure中的两个原子(在JVM上)具有相同的值是同一个原子吗? (即Clojure的原子存储机制如何工作?)

4 个答案:

答案 0 :(得分:20)

首先,“atom”在Clojure中的含义与大多数其他Lisp中的含义不同。见http://clojure.org/atoms

Clojure的=函数使用 value 为基础的相等。因此,具有相同值的两个对象将=,即使它们存储在内存中的不同位置。

要测试两个对象是否实际上是同一个对象,请在内存中的同一地址使用identical?函数。

答案 1 :(得分:6)

我认为'a和'a将成为不同的Java对象。我相信这证实了怀疑:

user> (def foo 5)
#'user/foo
user> (System/identityHashCode 'foo)
578999228
user> (System/identityHashCode 'foo)
1724482638

如果你看一下Clojure中Symbol的实际实现,你会看到一个符号由命名空间和一个名字组成,那些字符串必须是实习字符串。 Symbol.equals()方法依赖于对这两个字符串进行身份检查,依赖于字符串实习。

答案 2 :(得分:4)

我将解释Common Lisp部分:

在Common Lisp中(eq'a'a)总是返回T.

原因:在阅读时,读者查找 a ,对于 a ,它将查找相同的符号 a 。由于任何符号都是EQ,因此表达式总是返回T.

对于大多数类型的对象都是如此,但有一些例外。例如,数字和字符在Common Lisp中不是必需的EQ。原因是效率。要比较它们,如果它们是相同的数字或相同的字符,可以使用函数EQL。

答案 3 :(得分:4)

为了增加Alex和Stuart的答案,Clojure中的符号无论何时identical?都不能成为=,因为它们可能带有元数据。两个具有相同.name.namespace组件但元数据不同的符号将为=,但不会为identical?

可以想象,可以安排两个具有相同元数据,命名空间和名称的符号永远是identical?,但这是(1)两个麻烦没有实际收益(因为你还有一些符号=但不是identical?),(2)与可能携带元数据的类型通常应该比较值相等(元数据不贡献)的想法相反,而实际指针相等应该是保留用于特殊情况(主要涉及互操作)。

请注意,Clojure关键字是一种单独的类型,=确实等同于identical?。 (很明显,他们不能附加元数据。)