3

我有两个“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
...

:use如果我添加显式,我只能让第二个项目运行bar.clj

(:use clojure.set)

第一个项目虽然没有这个声明。为什么会有不同的行为?

更新

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

:eval-in-leiningen true
4

2 回答 2

4

如果您希望本地符号引用该名称空间中的名称,则只需声明使用名称空间。否则,您可以拼出要使用的每个 var 的全名。参见http://clojure.org/namespaces的第一页

普通函数通常存储在vars 中,您可以通过完整拼写名称(clojure.core/+ 1 2)或通过在封闭的命名空间中使用符号来refer访问它。例如,我们可以从一个名为 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)   

虽然+如果我们拼出var包含它的全名,我们可以使用该函数。

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

然后您可以通过调用使符号+引用它在 clojure.core 中所做的相同 varrefer

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


至于您的错误,在以下情况下往往会发生这种情况:

  • 您在该命名空间中运行(use 'clojure.set)(require 'clojure.set)从 REPL
  • 从 clojure.set 调用函数的代码实际上并未被调用,导致您看不到错误。
  • (ns foo.bar (:use clojure.clj))在一个项目的文件顶部的形式中声明,而不是在另一个项目中
于 2012-12-29T00:39:08.940 回答
3

Clojure 中的依赖关系的行为与大多数其他动态语言中的非常相似:除非您明确需要命名空间,否则其中的符号将不可用,因为命名空间尚未加载到运行时中;但是,一旦加载了命名空间,它的符号就可以从所有命名空间中使用,这解释了您所看到的行为。不一致是由文件加载到运行时的详细顺序造成的。

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

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

    (require [clojure.string :as s])

    这给你(s/join "," coll)

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

    (require [clojure.string :refer [join]])

    这给了你(join "," coll)

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

    (require [clojure.string :as s :refer [join]])

    这给了你(join "," coll)以及(s/join "," coll)

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

    (require [clojure.string :refer :all])

注意:演示的语法仅在(ns ...)表单内有效。当require用作独立形式时,必须明确引用所有符号。

如您所见,您所需要的(从 Clojure 1.4 开始)就是require,而use现在对于不需要声明前缀的情况来说只是一个小小的便利。

(use clojure.string)是相同的(require [clojure.string :refer :all])

(use [clojure.string :only [join]])是一样的(require [clojure.string :refer [join]])

于 2012-12-30T12:04:10.013 回答