我發現我們不需要'(ns ...)
,因爲ns是一個宏。 但是,爲什麼我們需要'在(require '[...])
?我認爲Clojure的矢量是避免的一種奇特的方式,但現在我在這裏看到一個。爲什麼我們需要'in(require'[...]])與Clojure?
我們使用(require 'clojure.string)
所以require
似乎是一個函數,但是當我們作爲一個參數給出時,我們不會引用一個向量。
從沒有引用該錯誤消息是也混亂。
我發現我們不需要'(ns ...)
,因爲ns是一個宏。 但是,爲什麼我們需要'在(require '[...])
?我認爲Clojure的矢量是避免的一種奇特的方式,但現在我在這裏看到一個。爲什麼我們需要'in(require'[...]])與Clojure?
我們使用(require 'clojure.string)
所以require
似乎是一個函數,但是當我們作爲一個參數給出時,我們不會引用一個向量。
從沒有引用該錯誤消息是也混亂。
這是因爲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,因爲它是和它傳遞給需要之前報價爲你,所以你不必。
生態位是:引用一個向量本質上是引用向量形式內的每個子形式。
user> (= '[a b c] ['a 'b 'c])
=> true
的require
形式可採取任一引用符號,參考命名空間,或者它可以採取引用符號將進一步限制的向量。
相關,幾乎重複:http://stackoverflow.com/q/32783187/124319 – coredump