为什么可以';我使用Clojure在do中声明名称空间和方法

为什么可以';我使用Clojure在do中声明名称空间和方法,clojure,namespaces,Clojure,Namespaces,我尝试在clojure中编写一个宏,用于设置名称空间并自动向其中添加一些方法。我的宏不工作,我跟踪到一个do语句。不可能在do中声明一个新名称空间,然后立即在该名称空间中声明一个方法。为什么? 这不起作用: (ns xyz) (do (ns abc) (prn *ns*) (defn tst[] (prn "test" *ns*))) (prn "after" *ns*) (tst) 这是有效的(do之前的名称空间声明): 谢谢你的阅读, Markus这是一个“宏扩展时间”与“运

我尝试在clojure中编写一个宏,用于设置名称空间并自动向其中添加一些方法。我的宏不工作,我跟踪到一个do语句。不可能在do中声明一个新名称空间,然后立即在该名称空间中声明一个方法。为什么?

这不起作用:

(ns xyz)
(do
  (ns abc)
  (prn *ns*)
  (defn tst[] (prn "test" *ns*)))

(prn "after" *ns*)
(tst)
这是有效的(do之前的名称空间声明):

谢谢你的阅读, Markus

这是一个“宏扩展时间”与“运行时间”的问题。是否希望在编译程序时或用户运行程序时出现(是否执行)中的代码?
(ns…)行由读取器展开,然后由编译器使用,以决定将生成的编译代码放在何处。

如果我理解正确,ns将设置变量的顶级绑定,告诉编译器的其余部分它正在构建代码的名称空间。作为一个实验,请尝试思考(prn…)表达式应该放在哪个名称空间中。

您的代码没有做您可能认为它做的事情。函数
tst
将在函数运行时而不是定义时打印变量*ns*的值


它在您作为第一个参数提供的名称空间中计算其主体,从而允许您将函数添加到当前名称空间以外的名称空间。

实际上,您的代码碰巧使用Clojure>1.0,但不要依赖于此! 编译并执行每个顶级表单:

(ns xyz) ; compiled with current ns / exec sets the current ns to xyz
(do ; the whole form is compiled inthe current ns (xyz) so it defines xyz/tst
  (ns abc)
  (prn *ns*)
  (defn tst[] (prn "test" *ns*)))
; the form above is executed: it sets the new current ns 
; and the value for xyz/tst

(prn "after" *ns*) ; we are in abc
(tst) ; abc/tst doesn't exists
在clojure>1.0中,顶层的do a是“展开的”,因此您的代码现在相当于:

(ns xyz)
; (do
(ns abc)
(prn *ns*)
(defn tst[] (prn "test" *ns*));)

(prn "after" *ns*)
(tst)

啊,谢谢。这就解释了。一旦发布稳定的clojure版本>1.0,我将记住这一点,以简单地使用宏。这是作为运行时测试。无论如何,您的使用ns技巧非常有用,因为我可以使用它来获得所需的功能。
(ns xyz
  (:use clojure.contrib.with-ns))

(with-ns (create-ns 'abc)
  (defn tst [] (print "defined in namespace abc")))
(ns xyz) ; compiled with current ns / exec sets the current ns to xyz
(do ; the whole form is compiled inthe current ns (xyz) so it defines xyz/tst
  (ns abc)
  (prn *ns*)
  (defn tst[] (prn "test" *ns*)))
; the form above is executed: it sets the new current ns 
; and the value for xyz/tst

(prn "after" *ns*) ; we are in abc
(tst) ; abc/tst doesn't exists
(ns xyz)
; (do
(ns abc)
(prn *ns*)
(defn tst[] (prn "test" *ns*));)

(prn "after" *ns*)
(tst)