我们知道当我们将符号发送到REPL时,Clojure会将符号解析为var,并获取当前var绑定的值。我们还知道,当一个var对象被namespace内部引用时,它是稳定的,因此我们可以动态地修改程序的运行行为(通过重新定义var的绑定)。
但这里有一个我不理解的现象。
REPL处理过程的截图
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).
第一个问题:值99在哪里?它曾由#'a解析,但似乎在执行#'a后变成了词法绑定。是吗?
第二个问题:在另一个命名空间(该命名空间引用了#'a)执行(var a)后,为什么#'a会以未绑定状态回收到内部?这似乎创建了一个新的var来满足状态。