在Common LISP的一些实现中,我们可以说对于以下表达式
(eq 'a 'a)
是true
,因为'a
和'a
是“相同的原子”。
这可能是依赖于实现的,但似乎短语(在流行的LISP教学书中使用)假设相同值的原子存储在内存中的相同位置。
在Java中,两个具有相同值的实习字符串存储在内存中的相同位置。
现在JVM上的Clojure继承了Java的遗产,但是说Clojure中的两个原子(在JVM上)具有相同的值是同一个原子吗? (即Clojure的原子存储机制如何工作?)
答案 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?
。 (很明显,他们不能附加元数据。)