2024年Clojure调查问卷!中分享您的想法。

欢迎!请参阅关于页面了解有关如何使用此工具的更多信息。

0
命名空间和变量
编辑

我们知道,当我们向REPL发送一个符号时,Clojure会将该符号解析为变量,并获取当前变量绑定的值。我们还知道,当 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会以未绑定状态回内联?这似乎创建了一个新的变量来满足状态。

1 答案

+2

对概念进行一些回顾可能会很有帮助。命名空间包含一群命名(符号),这些命名与变量进行映射。变量是一个值的容器。def 将一个名称映射到当前命名空间中的一个变量。refer 将当前命名空间中的名称映射到不同命名空间中的变量。

问题1:ns-unmap 从 ns-a 中删除了符号到变量的映射,但它不会销毁变量。变量仍然存在(并且由 ns-b 中的 refer 引用)。

问题2:`var` 是一个特殊形式(在编译器中实现),它可能执行的操作与你认为的不同。`var` 将解析为变量对象(在这里,编译时 `ns-b` 中的符号 `a` 解析为变量,即 `'ns-a/a'(不是变量对象,但这是一个令牌!!)。然后通过查找 ns-a 中的变量来评估它(这不存在)。我认为这里让人困惑的是特殊形式的编译(而且仅由于 `var` 才会发生)。

...