2
votes

I was browsing core.clj in Clojure's source code and came across the definition of defn. The function it defines takes several arguments, the first of which are &form and &env:

(def
 defn (fn defn [&form &env name & fdecl]
  ;; ...
  ))

Do these names take on special meaning because they start with &?

I know about rest args and the shorthand anonymous function var %&, but this doesn't seem to be either of those things.

I wasn't able to find anything about this syntax in the Reader reference, which doesn't mention & explicitly:

Symbols begin with a non-numeric character and can contain alphanumeric characters and *, +, !, -, _, ', ?, <, > and = (other characters may be allowed eventually).

Reading Clojure Characters also doesn't appear to mention this. resolve includes an &env arg in its doc string but doesn't elaborate.

1
Despite what the Reader Reference says, "&" is already accepted as a character anywhere in a symbol: (let [&a 1, a&b 2] [&a a&b]) => [1 2]. - Thumbnail

1 Answers

8
votes

The symbols &form and &env represent special variables used in Clojure macros: https://clojure.org/reference/macros#_special_variables.

In particular, you may use the &form variable to access the line number at which the macro is being evaluated

(:line (meta &form))

which is useful in printing error messages, etc.


Side note on searching for symbol-heavy terms:

SymbolHound.com is a search engine that does not elide symbols like Google, so you can often find results there that you can't other places. Searching for clojure &form yields results.


Update

Looking at the source code we see that in the Clojure bootstrapping process, fn is a macro making use of fn*:

(def
 ^{:macro true
   :added "1.0"}
 fn (fn* fn [&form &env & decl] 
         (.withMeta ^clojure.lang.IObj (cons 'fn* decl) 
                    (.meta ^clojure.lang.IMeta &form))))

So that is how the compiler injects &form, etc.