Если этого достаточно для того, чтобы вы захотели заменить (набор) основных макросов, вы можете попробовать этот подход:
(ns huge.core
(:refer-clojure :exclude [defn]))
(defmacro defn [name & defn-tail]
(assert (nil? (resolve name))
(str "Attempting to redefine already defined Var "
"#'" (.name *ns*) "/" name))
`(clojure.core/defn ~name ~@defn-tail))
Затем любая попытка переопределитьсуществующий Var с defn
потерпит неудачу:
user=> (defn foo [] :foo)
#'user/foo
user=> (defn foo [] :bar)
AssertionError Assert failed: Attempting to redefine already defined Var #'user/foo
(nil? (resolve name)) user/defn (NO_SOURCE_FILE:2)
Вы также можете заменить defmacro
;в этом случае вам придется вызывать clojure.core/defmacro
при определении вашего собственного варианта.
Обычная, неукрашенная def
- это специальная форма, которая получает магическую обработку от компилятора, поэтому вы все равно можете перезаписать существующие Vars с ее помощью,Если вы также хотите защититься от столкновений имен на этом фланге, вы можете переключиться на что-то вроде defvar
(раньше было доступно в clojure.contrib.def
) с аналогичным пользовательским утверждением.