将*ns*绑定到其他内容后修改变量

set*_*hwm 1 clojure

我不清楚为什么在下面的代码片段中,foo是在"user"命名空间中定义的,而不是在绑定闭包中绑定到*ns*的那个.有人可以解释我错过的东西吗?

$ clj
Clojure 1.4.0

user=> (let [nspace (create-ns (gensym "sandbox"))]
            (binding [*ns* nspace]
                     (print (ns-name *ns*))
                     (def foo 6)))
sandbox3#'user/foo

user=> foo
6

user=> (in-ns 'sandbox3)
#

sandbox3=> foo
CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0)

sandbox3=> (def bar 7)
#'sandbox3/bar

sandbox3=> bar
7

sandbox3/user=> (in-ns 'user)
#

user=> foo
6

user=> bar
CompilerException java.lang.RuntimeException: Unable to resolve symbol: bar in this context, compiling:(NO_SOURCE_PATH:0) 

Mic*_*zyk 5

def将在编译时确定将创建Var 的命名空间.然后绑定不起作用(binding引入运行时绑定).

def应仅用于顶级或顶级let表单之类的内容.另一个偏离简单的顶层def,人们应该更加谨慎.例如,在许多方面binding肯定与顶级类似,let并且def将使用预期的线程局部绑定来评估表达式的值部分:

user=> (let [nspace (create-ns (gensym "foo"))]
         (binding [*ns* nspace]
           (def foo *ns*)))
#'user/foo
user=> foo
#<Namespace foo3>
Run Code Online (Sandbox Code Playgroud)

但是,首先创建Var的方式在执行到达def表单时完全不受运行时状态的影响.

要动态创建Vars,请使用intern- 它是具有完全可预测行为的常规函数​​.