Clojure 当声明名称空间的用法是必需的,并且它是';不是吗?

Clojure 当声明名称空间的用法是必需的,并且它是';不是吗?,clojure,Clojure,我有两个“lein”项目,在两个测试文件中有完全相同的代码: ... clojure.set/union ... 第一个项目成功编译并运行。第二个错误是: Exception in thread "main" java.lang.ClassNotFoundException: clojure.set, compiling:(foo/bar.clj:14) ... Caused by: java.lang.ClassNotFoundException: clojure.set ... 如果我在

我有两个“lein”项目,在两个测试文件中有完全相同的代码:

... clojure.set/union ...
第一个项目成功编译并运行。第二个错误是:

Exception in thread "main" java.lang.ClassNotFoundException: clojure.set, compiling:(foo/bar.clj:14)
...
Caused by: java.lang.ClassNotFoundException: clojure.set
...
如果我在
bar.clj中添加显式
:use
,我只能运行第二个项目

(:use clojure.set)
但是第一个项目没有这个语句。为什么会有不同的行为

更新

没有发生异常的第一个项目在
project.clj
中有以下声明:

:eval-in-leiningen true

如果希望本地符号引用名称空间中的名称,则只需声明名称空间的使用。否则,您可以拼写出要使用的每个变量的全名。请参阅第页的第一页

正常函数通常存储在
var
s中,您可以通过完全拼写名称
(clojure.core/+1 2)
或使封闭命名空间中的符号
引用
来访问这些函数。例如,我们可以从一个名为bar的完全空白的名称空间开始。它甚至不会从它的核心Clojure功能开始:

foo> (in-ns 'bar)
#<Namespace bar>
bar> (+ 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: + in this context, compiling:(NO_SOURCE_PATH:1)   
然后,通过调用
refere

bar> (clojure.core/refer 'clojure.core)
nil
bar> (+ 1 2)
3

至于您的错误,这样的情况往往发生在:

  • 您在该命名空间中从REPL运行
    (使用'clojure.set)
    (需要'clojure.set)
  • 从clojure.set调用函数的代码实际上没有被调用,导致您看不到错误
  • 它在
    (ns foo.bar(:use clojure.clj))
    表单中声明在一个项目的文件顶部,而不是在另一个项目中

Clojure中的依赖项的行为与大多数其他动态语言中的行为非常相似:除非您明确要求名称空间,否则名称空间中的任何符号都将不可用,因为名称空间不会加载到运行时中;但是,一旦加载了名称空间,它的符号就可以从所有名称空间中获得,这解释了您看到的行为。不一致的原因是文件加载到运行时的顺序的详细信息

命名空间依赖性问题的其他方面仅涉及取消引用外部命名空间符号的方便程度:

  • 您可以声明要使用的命名空间前缀,而不是全名:

    (需要[clojure.string:as s])

    这将为您提供
    (s/join”,“coll)

  • 您可以将外部命名空间中的某些符号引用到主命名空间中。这会将本地符号绑定到外部命名空间中相同的命名对应项:

    (需要[clojure.string:参考[join]])

    它为您提供了
    (join),“coll)

  • 您既可以声明前缀,也可以引用特定符号:

    (需要[clojure.string:as s:引用[join]])

    这将为您提供
    (join),“coll”
    以及
    (s/join),“coll)

  • 您可以将整个命名空间引用到您的主命名空间中:

    (需要[clojure.string:refere:all])

注意:演示的语法仅在
(ns…
表单中有效。当require用作独立形式时,所有符号都必须显式引用

正如您所看到的,您所需要的(从Clojure 1.4开始)就是require,而对于不需要声明前缀的情况,使用现在只是一个小小的方便

(使用clojure.string)
(要求[clojure.string:refere:all])相同。


(使用[clojure.string:only[join]])
(需要[clojure.string:refere[join]])

相同,如果您包含两个项目中的名称空间声明,它将帮助我改进我的回答这不是真的。你必须
要求你想要使用的
名称空间,即使你拼出了你正在使用的var的全名。Java类按照您所说的方式工作。
bar> (clojure.core/refer 'clojure.core)
nil
bar> (+ 1 2)
3