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

pro*_*eek 5 clojure

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

我们用(require 'clojure.string)这样require似乎是一个功能,但是当作为参数给定的,我们不要引用一个载体.

在此输入图像描述

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

Mic*_*ent 6

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

user=> [clojure.set :as s]
CompilerException java.lang.ClassNotFoundException: clojure.set
Run Code Online (Sandbox Code Playgroud)

从而产生错误.

但是,它ns是作为宏实现的,并且可以完全控制if或何时进一步评估其参数,因此您不需要引用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
Run Code Online (Sandbox Code Playgroud)

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


Dav*_*zhu 5

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

user> (= '[a b c] ['a 'b 'c])
=> true
Run Code Online (Sandbox Code Playgroud)

require形式可以采用引用命名空间的引用符号,也可以采用引用符号的向量,以进一步限制。