Продлить своп!поведение для типа ноль в Clojure - PullRequest
0 голосов
/ 23 января 2019

предположим, у меня есть var atom-var

(def atom-val (atom []))

Также предположим стандартное поведение атома:

(swap! atom-val conj {:b "2"})
=> #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}]
(@atom-val)
=> #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}]

Я хочу создать такое же поведение, с которым оно будет работатьобъект nil, но без действий:

(def atom-val nil)
(swap! atom-val conj "New val")

Конечно, я получу исключение NullPointerException.Но я хочу, чтобы ничего не случилось, подавить это.Мне не нужно каждый раз писать try, мне просто нужно описанное поведение.

Я вижу, что swap! - это функция, atom - это функция,атом возвращает clojure.lang.IAtom , clojure.lang.IAtom является интерфейсом.Я не могу расширить интерфейс.Как я могу получить описанное поведение?

Хорошо, у меня есть глобальная динамическая переменная, равная nil

(def ^:dynamic  atom-val nil). 

Всякий раз, когда создается поток (это обработчик кольца с compojure), яЯ связываю atom-val с

(defn func [handler] 
   (fn [request]
     (binding [atom-val (atom [])]
        (handler request)
    )
 )

Итак, у меня есть такая форма в различных функциях:

(swap! atom-val conj "New val"). 

Я могу запускать ее везде много раз (внутри / снаружи разных функций),Очень плохо каждый раз проверять, является ли atom-val нулевым или нет.Функции могут сделать swap! , но иногда atom-val не может быть правильно инициализирован (когда функция выполняет своп! Вне обработчиков кольца перед привязкой).

Итак, я решил сделать это следующим образом: я бы хотел расширить протокол swap! для Atom и когда nil (когда atom-val равен nil )он не должен выдавать исключение NullPointerException.

Ответы [ 3 ]

0 голосов
/ 23 января 2019

Итак, вы хотите swap! на ноль?Я не уверен, что вы имели в виду с действиями и бездействием.

Это определенно не имеет смысла (по крайней мере для меня) к swap! нулевому значению;если это для вас, вы должны рассмотреть, что атомы на самом деле.Возможно, вы имеете в виду, что если дать ноль вместо ссылки на атом, swap! ничего не сделает.

Если это так, то вы можете просто сделать свою собственную функцию, чтобы выполнить эту проверку для вас:

(defn nilable-swap!
  [a f]
  (when a (swap! a f)))

Но Я действительно не рекомендую вам делать это, если это то, что вы хотите сделать, это указывает на плохой дизайн и поток управления.Конечно, имеет смысл проверить, равна ли ваша атомная ссылка нулю, если вы не уверены, но вам действительно нужно регулярно проверять это?действительно ли нет смысла, когда вы знаете, что у вас есть ссылка на ваш атом?

Я думаю Я мог бы ответить на ваш вопрос, но если я неправильно понял, не стесняйтесь уточнить, и я обновлю /удалите ответ.

0 голосов
/ 24 января 2019

Если вы хотите атом, который ничего не делает, вы можете написать:

(def noop-atom
  (reify clojure.lang.IAtom
    (reset [_ _])
    (swap [_ _])
    (swap [_ _ _])
    (swap [_ _ _ _])
    (swap [_ _ _ _ _])
    (compareAndSet [_ _ _])))

Затем вы можете использовать этот атом в качестве корневого значения динамической переменной.

Если ваша цель - управлять состоянием в течение жизненного цикла запроса / ответа на звонок, вы можете написать пользовательское промежуточное ПО .

0 голосов
/ 23 января 2019

Вам нужно использовать fnil.См. https://clojuredocs.org/clojure.core/fnil

Пример:

(def atom-val nil)
(def nil-swap! (fnil swap! (atom [])))

(nil-swap! atom-val conj "New val") => ["New val"]

И не забывайте постоянно держать вкладку браузера открытой для Clojure CheatSheet всегда!

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