clojure require syntax rationale

2019-03-11 01:55发布

问题:

I'm having a hard time understanding (and therefore remembering) the clojure require syntax described here: http://clojuredocs.org/clojure_core/1.3.0/clojure.core/require. It seems both counter intuitive and non-uniform.

For example, in the following why is this vector required to be quoted:

(require '[clj-json.core :as json])

Counter intuitive because normally vectors are not quoted in clojure (lists are quoted and vectors are treated as data).

And non-uniform because in this case the vector is NOT quoted:

(ns xxx 
    (:require [clj-json.core :as json]))

I realize that the require function and the :require usage inside the ns macro are only optically similar, but still.

There are other pieces of weirdness as well, for example I can do this:

(require '(clj-json.core))

But I can't do this:

(require '(clj-json.core :as json))

Can someone answer these questions:

  1. in the first example why does the vector need to be quoted?
  2. why does it not need to be quoted in the ns macro?
  3. why does the list notation not allow :as?

I'm wondering if there's reasons why things are the way they are, or if the inconsistency was just not noticed at design time.

回答1:

  1. in the first example why does the vector need to be quoted?

require is a function, so you have to quote them in order to prevent evaluation. Otherwise those symbols will be looked up in the current context, likely resulting in an error or possibly unexpected behavior. By the way, I think this not quite right: "Counter intuitive because normally vectors are not quoted in clojure (lists are quoted and vectors are treated as data)."

It may be counter intuitive to you, however there's nothing wrong with quoting vectors (or maps or sets). I often do when quickly testing something at the REPL, and don't want to type a : for each keyword in a map or vector, for instance:

user=> '{a 1 b 2 c 3}

rather than:

user=> {:a 1 :b 2 :c 3}

The first is very marginally faster to type if I just want to quickly get some data to test something with.

  1. why does it not need to be quoted in the ns macro?

Macros don't evaluate their arguments, they're sort of lazier than normal function calls, so the symbols (clj-json.core and json) don't need to be quoted to prevent evaluation.

  1. why does the list notation not allow :as?

Sorry, I don't know the answer to this one.

Ah, I took a look at the docs for require and found out. There's another form supported:

"The following would load the libraries clojure.zip and clojure.set abbreviated as 's'."

(require '(clojure zip [set :as s]))