Clojure `:direct-linking` Default Transition: Production Compilation vs REPL Safety
0 reputation · 24 Apr 2025, 09:03 UTC
0 reputation · 24 Apr 2025, 09:03 UTC
Clojure 1.8.0 added direct linking through the :direct-linking key in *compiler-options*, replacing Var dereference call sites with direct function references. The default remains false, preserving runtime redefinition semantics that REPL-driven workflows rely on. For low-traffic or batch workloads that start frequently, enabling this feature can reduce allocation and startup overhead, though the savings are bounded by JVM baseline costs and apply only to var indirection.
The unresolved decision is whether Clojure should provide a production-specific default for ahead-of-time compilation. No official split between development and production defaults exists, so teams must manually isolate build profiles. Enabling direct linking globally risks silent behavioral divergence when code depends on runtime redefinition, such as hot reloading or certain test harnesses. Without a documented compatibility boundary, operators of low-traffic services lack clear guidance on when the cost trade-off is safe.
Should the compiler adopt a separate default for production or AOT compilation units that enables direct linking while leaving the REPL default unchanged? What compatibility guarantees would apply to libraries compiled under mixed settings? What role can build tooling play in exposing this boundary without forcing every project to maintain divergent development and deployment configurations?
33775 reputation · 24 Apr 2025, 17:53 UTC
No. Clojure should not adopt a separate production default for :direct-linking. The compiler has no built-in development/production split, and changing the default silently would break runtime redefinition in any code path that loads AOT-compiled libraries. Build tooling, not the compiler, should own the boundary.
:direct-linking replaces Var dereference with direct function references at compile time. With the default false, call sites check the Var root on every invocation, so redef and alter-var-root take effect immediately. Setting it to true bakes in the current function reference, so later redefinitions are invisible at those call sites. Because Clojure does not tag compiled classes with the compiler mode that produced them, mixing direct-linked and non-direct-linked artifacts in the same deployment creates an invisible compatibility boundary: some call sites update, others do not.
:direct-linking defaults to false in Clojure 1.8.0 and later.:direct-linking automatically; it must be set in *compiler-options*.Var.deref and call the resolved function directly.*compiler-options* to {:direct-linking true} only in the AOT build profile, never in the REPL profile.redef, alter-var-root, or middleware that redefines vars at runtime.javap -c and confirm direct-linked call sites lack Var.deref.Does the production workload use runtime redefinition, hot reloading, or test harnesses that alter vars after AOT compilation?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.