We know that when we send a symbol to REPL, Clojure will resolve the symbol to var, and get the value which is currently the var's bindings. And we also know that var object is stable when it is interned by namespace, so we can dynamically modify the runtime behavior of a program(by re-def-ing the var's bindings).
But here comes a strange things that I don't understand.
Screenshot of the REPL process
user=> (ns ns-a)
ns-a=> (def a 42)
ns-a=> a
;;42
ns-a=> (ns ns-b)
ns-b=> (refer 'ns-a)
ns-b=> a
;;42
ns-b=> (var a)
#'ns-a/a
ns-b=> (in-ns 'ns-a)
ns-a=> a
;;42
ns-a=> (def a 99)
ns-a=> a
;;99
ns-a=> (in-ns 'ns-b)
ns-b=> a
;;99
;;nothing special so far
ns-b=> (in-ns 'ns-a)
ns-a=> (ns-publics *ns*)
;;{a #'ns-a/a}
;;see, it's interned
ns-a=> (ns-unmap *ns* 'a)
;;lets unmap the (var a) from ns-a
ns-a=> (ns-publics *ns*)
;;{}
ns-a=> a
;;Syntax error compiling at (REPL:0:0).
;;Unable to resolve symbol: a in this context
ns-a=> (var a)
;;Syntax error compiling var at (REPL:1:1).
;;Unable to resolve var: a in this context
;;(var a) is nowhere.
ns-a=> (in-ns 'ns-b)
ns-b=> a
;;99
;;the referred symbol a still evaluates to 99.
ns-b=> (var a)
;;#'ns-a/a
;;yeah, (var a) is still somewhere.
ns-b=> (deref (var a))
;;#object[clojure.lang.Var$Unbound 0x4a68135e "Unbound: #'ns-a/a"]
;;What? (var a) is being unbound. Is this a new (var a)?
ns-b=> a
;;99
;;it is not resolved from (var a)?
ns-b=> (in-ns 'ns-a)
ns-a=> a
;;#object[clojure.lang.Var$Unbound 0x4a68135e "Unbound: #'ns-a/a"]
;;What? it comes back?
ns-a=> (def a 53)
;;Lets redefine (var a) to bind 53
ns-a=> a
;;53
ns-a=> (in-ns 'ns-b)
;;Lets switch back and check.
ns-b=> a
;;99
;;not changed
ns-b=> (deref (var a))
;;53
;;so I'm sure 99 it is not resolved from (var a).
The first question: where is the value 99 resides? It used to being resolved from #'a, but it seems being like a lexical bindings after #'a being unmapped. Is it?
The second question: why the #'a is interned back with unbound state after execute (var a) in another namespace(which has a refering to #'a)? Seems it create a new var to fullfill the state.