Избегайте переопределения имен переменных - PullRequest
5 голосов
/ 17 сентября 2011

В конкретном пространстве имен, над которым я работаю, у меня заканчиваются имена функций. Есть ли способ получить предупреждение, подобное тому, которое я получаю, если переопределить символ из другого пространства имен, если я повторно использую символ, который уже связан с функцией в том же пространстве имен?

Ответы [ 3 ]

4 голосов
/ 17 сентября 2011

Если этого достаточно для того, чтобы вы захотели заменить (набор) основных макросов, вы можете попробовать этот подход:

(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) с аналогичным пользовательским утверждением.

2 голосов
/ 17 сентября 2011

Это не совсем ответ на ваш вопрос, но может помочь избежать проблемы в зависимости от того, как используются функции в вашем пространстве имен.Вы можете превратить их в локальные функции, используя letfn , что позволяет повторно использовать имена для функций, которые используются только в контексте другой функции.

(defn main-fn [x]
  (letfn [(secondary-fn [x] (* x x))
          (another-fn [x] (secondary-fn (inc x)))]
    (/ (another-fn x) 4)))
1 голос
/ 17 сентября 2011

Даже если вы ограничиваетесь односимвольными именами функций, вы не рискуете закончиться, так как есть (около) 64 тысяч символов Unicode, любой из которых является допустимым именем функции.

Учитывая, что на самом деле у вас могут быть имена длиной в десять тысяч символов, вы находитесь на более безопасном месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...