2024年Clojure状态调查中分享您的想法!

欢迎!有关如何使用此功能,请查看关于页面以获取更多信息。

+1
编译器

Clojure中的关键字是缓存和内联的,这样

(identical? :a :a)

返回true。但符号却不这样做

(identical? 'a 'a)

返回false。

有什么原因吗?

2 答案

+4

selected
 
最佳答案

符号是上下文相关的,相同的符号实例可能具有不同的元数据。

元数据是有状态的,与内联的概念存在固有冲突。关键字没有元数据,但有快速的实体相等语义。
0

我相信答案的一部分是,关键字之所以要进行池化(interned)是为了在 maps(以及可能的其他数据结构)中更高效地使用内存和进行键查找,因为 Clojure 中的 = 在大多数情况下会先进行一次快速的 identical? 检查,如果它们相同,就返回 true。这使得关键字在用作 map 键时,与其他值相比,具有更好的性能特征,因为在 Clojure 程序中,关键字经常被用作 map 键。

尽管如此,关键字池化在它们初次被池化时确实会有性能成本。对于关键字而言,这通常并不是一个大问题,尤其是在大多数 Clojure 程序中,使用的关键字集合相对较小。对于阅读巨大的 JSON 文件并将大量的 JSON 键字符串转换为 Clojure 关键字的人来说,这是一个性能问题。过去对 Clojure 的一些改进就是出于这样的用例动机。我目前没有 JIRA 票夹在身边,但如果有人对此感兴趣的话,我可以查找到它们。

符号不是为了那些用例进行性能优化的,如果你尝试将它们用作 maps 中的键,那么将相对于性能稍微差一些,但我相信这也因此避免了在遇到新符号时池化的性能成本。

在 Common Lisp 中有一些类似的行为历史,可能还有其他 Lisp 家族语言。

...