为什么我们需要使用Clojure'in(require'[...]]?

时间:2015-11-07 02:18:26

标签: clojure

我发现我们不需要'(ns ...),因为ns是一个宏。 但是,为什么我们需要'(require '[...])?我认为Clojure的矢量是避免'的一种奇特方式,但现在我在这里看到了一个。

我们使用(require 'clojure.string)所以require似乎是一个函数,但是当作为参数给出时,我们不引用向量。

enter image description here

来自非引用的错误消息也令人困惑。

2 个答案:

答案 0 :(得分:6)

这是因为require是作为函数而不是宏实现的,因此它需要引用的libspec。不带引号的libspec将按如下方式进行评估:

user=> [clojure.set :as s]
CompilerException java.lang.ClassNotFoundException: clojure.set

因此产生错误。

但是,ns是作为宏实现的,并且可以完全控制是否或何时进一步评估其参数,因此您不需要引用libspec。您可以查看ns的宏展开,看看展开时会发生什么:

user=> (use 'clojure.pprint)
nil
user=> (pprint (macroexpand '(ns foo (:require [clojure.set :as s]))))
(do
 (clojure.core/in-ns 'foo)
 (clojure.core/with-loading-context
  (clojure.core/refer 'clojure.core)
  (clojure.core/require '[clojure.set :as s]))
 (if
  (.equals 'foo 'clojure.core)
  nil
  (do
   (clojure.core/dosync
    (clojure.core/commute
     @#'clojure.core/*loaded-libs*
     clojure.core/conj
     'foo))
   nil)))
nil

正如您所看到的,ns只是按原样使用libspec并在将其传递给require之前为您引用,因此您不必这样做。

答案 1 :(得分:2)

利基是:引用一个向量基本上引用了向量形式中的每个子形式。

user> (= '[a b c] ['a 'b 'c])
=> true

require表单可以使用带引号的符号,引用命名空间,也可以使用带引号的符号向量进行进一步的限制。