2015-11-07 82 views
4

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

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

enter image description here

从没有引用该错误消息是也混乱。

+0

相关,几乎重复:http://stackoverflow.com/q/32783187/124319 – coredump

回答

5

这是因为require是作为一个函数实现的,而不是一个宏,因此它需要一个带引号的libspec。不加引号的libspec将被评估如下:

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

因此产生错误。

但是,ns是作为一个宏实现的,并且完全控制是否或何时进一步评估它的参数,所以你不需要引用libspec。你可以看一下纳秒的宏扩展,看看会发生什么,当它展开:

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,因为它是和它传递给需要之前报价为你,所以你不必。

2

生态位是:引用一个向量本质上是引用向量形式内的每个子形式。

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

require形式可采取任一引用符号,参考命名空间,或者它可以采取引用符号将进一步限制的向量。