2015-11-07 36 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形式可採取任一引用符號,參考命名空間,或者它可以採取引用符號將進一步限制的向量。