Skip to content

Instantly share code, notes, and snippets.

@technomancy
Last active April 21, 2023 01:16
Show Gist options
  • Save technomancy/cc0e7800878c39e4c245fc041c11df4b to your computer and use it in GitHub Desktop.
Save technomancy/cc0e7800878c39e4c245fc041c11df4b to your computer and use it in GitHub Desktop.
Clojure namespaces, spec, and why they're confusing

To me, "require-and-automatically-visible" is violating the beauty of namespace. But, maybe I felt this way because I don't understand Clojure's registry or how require works.

I thought about this more, and I think I have a better understanding of why this feels strange. Clojure has one thing called "namespaces" which are clojure.lang.Namespace objects created by the ns macro. Functionally speaking they are a storage location which mostly just contain vars and references to vars in other namespaces. They are used for code organization: specifically for organizing vars and occasionally Java classes and interfaces.

Clojure also has a completely different thing called "namespaces" which are prefixes that get attached to keywords and symbols. These can interact with ns namespaces thru the reader in a handful of ways (for instance, ::double-colon keywords and symbols inside backtick forms are resolved according to the current clojure.lang.Namespace) but for the most part should be considered a distinct concept. There is no rule which says that a symbol's namespace must correspond to a namespace has a corresponding clojure.lang.Namespace object; if there were such a rule we couldn't use things like [org.clojure/clojure "1.9.0"] in your project.clj file. These are just arbitrary prefixes you can attach to things.

Maybe it would be clearer to think of them as names, not name spaces. With a clojure.lang.Namespace you can take it and look inside it; what other things exist in this space? With a symbol/keyword namespace, it's just an identifier; there's nothing more to it. There is no space unless you think of the mathematical definition of the term; closer to a coordinate plane than a reified location.

Now the problem here is that the introduction of spec means that it's even more confusing, because the second kind of namespace is now treated as a storage location as well! Specs are stored using namespaced keywords, which means they feel more like there is a clojure.lang.Namespace at play here, but there isn't. Specs are stored in a mirror-universe where the names follow keyword/symbol-namespace rules, not ns rules. (I think this is a mistake and that specs should be stored in a real ns but it's no good arguing about that since it's too late for that to happen.) But I think as long as you understand that there are two completely different meanings of the word "namespace" in Clojure, it helps avoid confusion.

@kenrestivo-stem
Copy link

Is it really too late to argue this? Spec is still alpha...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment