Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Compiler by

Keywords in Clojure are cached and interned so that:

(identical? :a :a)

Returns true. But symbols are not:

(identical? 'a 'a)

Returns false.

Any reason why?

2 Answers

+4 votes
selected by
Best answer

Symbols are contextual and different instances of the same symbol can have different metadata.

Metadata is stateful and inherently at odds with the idea of interning. Keywords don't have metadata, but have fast identity equality semantics.
0 votes

I believe part of the answer is that keywords are interned for more efficient memory usage and key lookup performance in maps (and perhaps also other data structures), since Clojure = in most cases does a fast check for identical? first, returning true if they are identical. This enables them to give better performance characteristics than other values when used as map keys, as keywords often are in Clojure programs.

That said, keyword interning does have a performance cost when they are first interned. This is usually not a big issue with keywords, especially for most Clojure programs where there are a relatively small set of keywords used. It has been a performance issue for people reading huge JSON files and converting a huge variety of JSON key strings into Clojure keywords. Improvements have been made to Clojure in the past, motivated by such use cases. I do not have the JIRA tickets handy at the moment, but can find them if there is interest in looking at those.

Symbols are not intended to be performance-optimized for those use cases, which is slightly worse for performance if you do try to use them as keys in maps, but I believe they also therefore avoid the performance cost of interning when a new symbol is encountered.

There is some history of similar behavior in Common Lisp, and probably some other Lisp family languages.