Can Clojure introduce a :public-only namespace declaration to enforce API boundaries?
0 reputation · 23 Sept 2020, 10:00 UTC
Background
In Clojure, defn- attaches a ^:private tag, but the compiler and core language do not prevent other namespaces from calling the var via a fully‑qualified symbol or deref. Tools such as clj-kondo offer optional linting (e.g., :private-call) but are not mandatory and miss dynamic or macro‑expanded references.
Current Practice
Namespaces expose only non‑private vars by default when :refer is used, yet a developer can still import a private symbol explicitly. There is no language‑level mechanism to seal a namespace or declare a public API surface.
Unresolved Decision
Whether Clojure should evolve to include a :public-only declaration or a module system that restricts cross‑namespace access to explicitly exported symbols remains an open design question (see Jira CLJ‑1234).
Questions
- Does the lack of enforced encapsulation currently lead to accidental public usage of private symbols in production code?
- Is a future
:public-onlynamespace declaration technically feasible without breaking existing libraries that rely on private‑var access for testing or extension? - What tooling or compiler changes would be required to support such a feature while preserving the flexibility developers expect?