在 clojure 中,(= 'a 'a) 指的是“同一个原子”吗?
在 Common LISP 的某些实现中,我们可以说以下表达式为
(eq 'a 'a)
true
,因为 'a
和 'a
是“相同的原子”。
这可能与实现相关,但似乎这个短语(在一本流行的 LISP 教学书中使用)假设相同值的原子存储在内存中的相同位置。
在Java中,两个具有相同值的interned字符串存储在内存中的相同位置。
现在 JVM 上的 Clojure 继承了 Java 的遗产,但是可以说 Clojure(在 JVM 上)中具有相同值的两个原子是同一个原子吗? (即Clojure的原子存储机制是如何工作的?)
In some implementations of Common LISP we can say that for the following expression
(eq 'a 'a)
Is true
because 'a
and 'a
are the "same atom".
This may be implementation dependent, but it seems the phrase (used in a popular LISP teaching book) assumes that atoms of the same value are stored in the same location in memory.
In Java, two interned strings of the same value are stored in the same location in memory.
Now Clojure on the JVM inherits Java's legacy, but is it true to say that two atoms in Clojure (on JVM) having the same value are the same atom? (ie how does Clojure's atom storage mechanism work?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,“原子”在 Clojure 中的含义与大多数其他 Lisp 中不同。请参阅 http://clojure.org/atoms
Clojure 的
=
函数使用值基于平等。因此,即使两个对象存储在内存中的不同位置,具有相同值的两个对象也会=
。要测试两个对象实际上是否是同一对象(位于内存中的同一地址),请使用
identical?
函数。First, "atom" has a different meaning in Clojure than in most other Lisps. See http://clojure.org/atoms
Clojure's
=
function uses value-based equality. So two objects with equal values will be=
even if they are stored in different locations in memory.To test if two objects are actually the same object, at the same address in memory, use the
identical?
function.我认为 'a 和 'a 在底层是不同的 Java 对象。我相信这证实了这种怀疑:
如果您查看 Symbol ,您会看到符号由命名空间和名称组成,并且这些字符串必须是内部字符串。 Symbol.equals() 方法依赖于字符串实习生对这两个字符串进行身份检查。
I think 'a and 'a are going to be different Java objects under the hood. I believe this confirms that suspicion:
If you look at the actual implementation of Symbol in Clojure, you'll see that a symbol consists of a namespace and a name and those Strings MUST be interned strings. The Symbol.equals() method relies on doing identity checks on those two strings, relying on string intern.
我将解释 Common Lisp 部分:
在 Common Lisp 中 (eq 'a 'a) 总是返回 T。
原因:在阅读时,读者查找 a,并且查找 a< /em> 它将查找相同的符号a。由于任何符号对其自身都是 EQ,因此表达式始终返回 T。
对于大多数类型的对象都是如此,但也有一些例外。例如,数字和字符在 Common Lisp 中并不是必需的 EQ。原因是效率。要比较它们是否是相同的数字或相同的字符,可以使用函数 EQL。
I'll explain the Common Lisp part:
In Common Lisp (eq 'a 'a) returns always T.
Reason: at read time, the reader looks up a, and for both a it will look up the same symbol a. Since any symbol is EQ to itself, the expression returns always T.
This is true for most types of objects, but with a few exceptions. Numbers and characters, for example, are not necessary EQ in Common Lisp. The reason for that is efficiency. To compare these if they are the same number or same character one can use the function EQL.
为了补充 Alex 和 Stuart 的答案,Clojure 中的符号无论何时
=
都不能变得相同?
,主要是因为它们可能携带元数据。具有相同.name
和.namespace
组件但元数据不同的两个符号将是=
但不相同? 。可以想象,可以这样安排事情,以便两个具有相同元数据、命名空间和名称的符号始终相同?一些符号
=
但不相同相同?
),(2)与通常应该比较可能携带元数据的类型的值相等性(元数据对此没有贡献)的想法相反),而实际的指针相等应保留用于特殊情况(主要涉及互操作)。请注意,Clojure 关键字是一种单独的类型,其中
=
实际上等同于identical?
。 (很明显他们不能附加元数据。)To add to Alex's and Stuart's answers, Symbols in Clojure could not be made to be
identical?
whenever they are=
mostly because they may carry metadata. Two Symbols which have the same.name
and.namespace
components but different metadata will be=
but notidentical?
.Things could conceivably be arranged so that two Symbols with the same metadata, namespace and name would always be
identical?
, but that is (1) two much hassle for no real gain (since you'd still have some Symbols=
but notidentical?
), (2) contrary to the idea that types which may carry metadata should normally be compared for value equality (to which metadata does not contribute), whereas actual pointer equality should be reserved for special situations (mostly involving interop).Note that Clojure Keywords are a separate type for which
=
is indeed equivalent toidentical?
. (So clearly they cannot have metadata attached.)