我相信答案的一部分是,关键字之所以要进行池化(interned)是为了在 maps(以及可能的其他数据结构)中更高效地使用内存和进行键查找,因为 Clojure 中的 =
在大多数情况下会先进行一次快速的 identical?
检查,如果它们相同,就返回 true。这使得关键字在用作 map 键时,与其他值相比,具有更好的性能特征,因为在 Clojure 程序中,关键字经常被用作 map 键。
尽管如此,关键字池化在它们初次被池化时确实会有性能成本。对于关键字而言,这通常并不是一个大问题,尤其是在大多数 Clojure 程序中,使用的关键字集合相对较小。对于阅读巨大的 JSON 文件并将大量的 JSON 键字符串转换为 Clojure 关键字的人来说,这是一个性能问题。过去对 Clojure 的一些改进就是出于这样的用例动机。我目前没有 JIRA 票夹在身边,但如果有人对此感兴趣的话,我可以查找到它们。
符号不是为了那些用例进行性能优化的,如果你尝试将它们用作 maps 中的键,那么将相对于性能稍微差一些,但我相信这也因此避免了在遇到新符号时池化的性能成本。
在 Common Lisp 中有一些类似的行为历史,可能还有其他 Lisp 家族语言。