Разрешение символов в пространстве имен require'd - PullRequest
3 голосов
/ 26 июля 2011

Я пишу небольшое приложение, которое включает функцию смены пароля с валидаторами для качества пароля. В настоящее время валидаторы указаны на карте примерно так:

(def validations
  {:min-length 6
   :max-length 32})

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

В пространстве имен проверок есть несколько функций проверки, которые обычно принимают форму:

(defn min-length [n s]
  {:req (str "be at least " n " characters long")
   :pass? (>= (.length (or s "")) n)})

Так что с функцией выше (min-length 3 "clojure") вернет {:req "be at least 3 characters long", :pass? true}.

Я могу подтвердить пароль с помощью этой функции в пространстве имен проверки с помощью этой функции:

(defn validate-new-password [password]
  (into {} (for [[k v] validations]
             [k (eval (list (-> k name symbol) v password))])))

В результате получается что-то вроде:

>(validate-new-password "clojure")
{:min-length {:req "be at least 6 characters long", :pass? true}, 
 :max-length {:req "be no longer than 32 characters long", :pass? true}, 
 :min-digits {:req "have at least 1 digit", :pass? false},  
 :allow-whitespace {:req "not contain spaces or tabs", :pass? true}, 
 :allow-dict-words {:req "not be a dictionary word", :pass? false}}

Каков наиболее практичный способ разрешения функций проверки, когда функция validate-new-password вызывается извне пространства имен проверки?

За последние недели я пробовал несколько подходов, но никогда не был доволен полученной формой (и ни один из них не сработал!).

Обычно я предполагаю, что вопрос «как символы разрешаются в пространстве имен: require'd при вызове функциями в этом пространстве имен?»

Меня также интересуют любые общие комментарии о моей реализации.

Ответы [ 2 ]

2 голосов
/ 26 июля 2011

Нет необходимости в eval, как в 98% случаев.

(defn validate-new-password
  [password]
  (into {} (for [[k v] validations]
             [k ((->> k name (symbol "your.name.space") resolve) v password)])))
1 голос
/ 26 июля 2011

Чтобы ответить на общий вопрос (из предпоследнего абзаца вопроса), символы обычно разрешаются во время компиляции - вы должны выходить из своего пути (то есть использовать resolve 1 ) отложить разрешение до времени выполнения.

Тем не менее, вам, вероятно, не нужно откладывать разрешение в этом случае, вам просто нужно :require пространство имен конфигурации в пространстве имен проверок и обратиться к config/validations в соответствующем месте.

Незначительные сложности могут возникнуть, если вы хотите, чтобы ваше пространство имен конфигурации зависело от пространства имен проверок (т. Е. :require или :use само по себе, или другое пространство имен, которое зависит от него). В этом случае вы можете указать несколько настроек в пространстве имен проверок и использовать их из config. E.g.:

(def validations (atom default-validations))
(defn set-validations! [vs]   (reset! validations vs))
(defn add-validation!  [k v]  (swap! validations assoc k v))

Затем поместите @validations вместо validations в validate-new-password.

В качестве альтернативы, вы можете поместить свои проверки по умолчанию в Var и предоставить функции для повторного связывания Var (предположительно, это должно произойти только один раз или очень редко, поэтому использование Var не должно быть проблемой):

(def validations default-validations)
(defn set-validations! [vs]  (.bindRoot validations vs))
(defn add-validation!  [k v] (alter-var-root validations assoc k v))

Теперь, если вы на самом деле не можете предсказать, во время написания кода, в каком пространстве имен вам нужно разрешить свой символ, тогда ответом котарака (с использованием resolve) будет путь.


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

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