【问题标题】:def a variable after binding *ns* to something else将 *ns* 绑定到其他东西后定义一个变量
【发布时间】:2014-03-14 07:15:46
【问题描述】:

我不清楚为什么在下面的代码 sn-p 中,foo 被定义在“用户”命名空间中,而不是我在绑定闭包中绑定到 *ns* 的那个。有人可以解释我缺少什么吗?

$ clj Clojure 1.4.0 user=> (let [nspace (create-ns (gensym "sandbox"))] (绑定 [*ns* nspace] (打印 (ns-name *ns*)) (def foo 6))) sandbox3#'用户/foo 用户=> foo 6 用户=> (in-ns 'sandbox3) # 沙盒3=> foo CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compile:(NO_SOURCE_PATH:0) sandbox3=> (def bar 7) #'sandbox3/栏 沙盒3=> 酒吧 7 sandbox3/user=> (in-ns '用户) # 用户=> foo 6 用户=>酒吧 CompilerException java.lang.RuntimeException:无法解析符号:此上下文中的 bar,正在编译:(NO_SOURCE_PATH:0)

【问题讨论】:

    标签: clojure


    【解决方案1】:

    你需要使用 eval:

       (let [nspace (create-ns (gensym "sandbox"))]
                (binding [*ns* nspace]
                         (print (ns-name *ns*))
                         (eval '(def foo 6))))
    

    eval 关注*ns*,但大部分 Clojure 不关注。

    编辑:是的,我只是建议一个人使用 eval :p

    对于上下文,我一直与 op 通信,他不想要真正的沙箱,因为他相信进入他的系统的代码,他只需要一种方法来评估不同命名空间内的输入代码!

    所以,如果你是这个问题的新手,而且你不是 sethwm,请参考 Marczyk 的回答。此解决方案非常特定于 OP 的用例,通常不是做很多事情的好方法。

    【讨论】:

    • 啊,不!如果您绝对必须在另一个命名空间中定义变量(您可能不需要),请使用intern。在这里使用eval 没有任何借口。
    【解决方案2】:

    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>
    

    然而,当执行到达def 表单时,首先创建 Var 的方式完全不受运行时状态的影响。

    要动态创建变量,请使用intern——它是一个具有完全可预测行为的常规函数​​。

    【讨论】:

    • 谢谢迈克尔。回复:实习生v def,我同意。但是,我将在绑定中解释其他人的代码,并且无法控制他们是否使用 def v intern。我正在制作一个穷人的沙盒。
    • 有趣的是,在这个问题之前,他和我实际上已经通过电子邮件进行了通信。我保证,他的用例是合法的。 :P
    • @Rayne - 凭你的良心吧。 :-P sethwm - 好吧,在这种情况下,Rayne 肯定是要联系的人。出于好奇,为什么不使用/改编clojail
    • @MichałMarczyk 他实际上并不需要沙箱——他信任将被评估的代码。他只需要评估基础设施。
    • @MichałMarczyk 也就是说,我已经编辑了我的答案,以引导新手回答你的答案,因为我的答案显然对他的特定用例有用,而对于其他任何事情都不是一个好主意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多