 
 (def
   ^{:arglists '([& keyvals])
-  :doc "keyval => key val
-      Returns a new hash map with supplied mappings.  If any keys are
-      equal, they are handled as if by repeated uses of assoc."
-      :added "1.0"}
-      hash-map hash-map*)
+    :doc "keyval => key val
+         Returns a new hash map with supplied mappings.  If any keys are
+         equal, they are handled as if by repeated uses of assoc."
+         :added "1.0"}
+  hash-map hash-map*)
 
 (def
   ^{:arglists '([& keys])
-  :doc "Returns a new hash set with supplied keys.  Any equal keys are
-      handled as if by repeated uses of conj."
-      :added "1.0"}
-      hash-set hash-set*)
+    :doc "Returns a new hash set with supplied keys.  Any equal keys are
+         handled as if by repeated uses of conj."
+         :added "1.0"}
+  hash-set hash-set*)
 
 (defn nil?
   "Returns true if x is nil, false otherwise."

(def

  ^{:doc "Same as (def name (fn [params* ] exprs*)) or (def
        name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
        to the var metadata. prepost-map defines a map with optional keys
        :pre and :post that contain collections of pre or post conditions."
        :arglists '([name doc-string? attr-map? [params*] prepost-map? body]
                    [name doc-string? attr-map? ([params*] prepost-map? body)+ attr-map?])
        :added "1.0"}
        defn (fn defn [&form &env name & fdecl]
               ;; Note: Cannot delegate this check to def because of the call to (with-meta name ..)
               (if (instance? Symbol name)
                 nil
                 (throw (ex-info "First argument to defn must be a symbol" {:form name})))
               (let [m (if (string? (first fdecl))
                         {:doc (first fdecl)}
                         {})
                     fdecl (if (string? (first fdecl))
                             (next fdecl)
                             fdecl)
                     m (if (map? (first fdecl))
                         (conj m (first fdecl))
                         m)
                     fdecl (if (map? (first fdecl))
                             (next fdecl)
                             fdecl)
                     fdecl (if (vector? (first fdecl))
                             (list fdecl)
                             fdecl)
                     m (if (map? (last fdecl))
                         (conj m (last fdecl))
                         m)
                     fdecl (if (map? (last fdecl))
                             (butlast fdecl)
                             fdecl)
                     m (conj {:arglists (list 'quote (sigs fdecl))} m)
                     m (conj (if (meta name) (meta name) {}) m)]
                 (list 'def (with-meta name m)
                       (cons `fn fdecl) ))))

(set-macro* #'defn)


(def

  ^{:doc "Like defn, but the resulting function name is declared as a
         macro and will be used as a macro by the compiler when it is
         called."
         :arglists '([name doc-string? attr-map? [params*] body]
                     [name doc-string? attr-map? ([params*] body)+ attr-map?])
         :added "1.0"}
  defmacro (fn [&form &env
                name & args]
             (let [prefix (loop [p (list name) args args]
                            (let [f (first args)]
                              (if (string? f)
                                (recur (cons f p) (next args))
                                (if (map? f)
                                  (recur (cons f p) (next args))
                                  p))))
                   fdecl (loop [fd args]
                           (if (string? (first fd))
                             (recur (next fd))
                             (if (map? (first fd))
                               (recur (next fd))
                               fd)))
                   fdecl (if (vector? (first fdecl))
                           (list fdecl)
                           fdecl)
                   add-implicit-args (fn [fd]
                                       (let [args (first fd)]
                                         (cons (vec (cons '&form (cons '&env args))) (next fd))))
                   add-args (fn [acc ds]
                              (if (nil? ds)
                                acc
                                (let [d (first ds)]
                                  (if (map? d)
                                    (conj acc d)
                                    (recur (conj acc (add-implicit-args d)) (next ds))))))
                   fdecl (seq (add-args [] fdecl))
                   decl (loop [p prefix d fdecl]
                          (if p
                            (recur (next p) (cons (first p) d))
                            d))]
               (list 'do
                     (cons `defn decl)
                     (list 'set-macro* (list 'var name))
                     (list 'var name)))))

(set-macro* #'defmacro)

