Бесплатный курс по clojure. Зарегистрируйтесь для отслеживания прогресса →

Clojure: Наблюдатели

Помимо атомов и агентов, в Clojure существуют наблюдатели, их основное использование заключается в наблюдении за изменяемым ресурсом (издалека напоминает супервизоров из Elixir/Erlang, но более простых).

Рассмотрим несколько примеров:

(def my-atom (atom 0))

; добавим наблюдателя для нашего атома, у наблюдателя должно быть уникальное имя
(add-watch my-atom "my-watcher"
; обратите внимание на аргументы, которые передаются в функцию, вызываемую наблюдателем при изменении состояния
  (fn [key variable old-state new-state]
    (println key variable old-state new-state)))
#object[clojure.lang.Atom 0x673d073a {:status :ready, :val 0}]

(swap! my-atom inc)
my-watcher #object[clojure.lang.Atom 0x673d073a {:status :ready, :val 1}] 0 1
1

(swap! my-atom (fn [state] (* state 4)))
my-watcher #object[clojure.lang.Atom 0x673d073a {:status :ready, :val 4}] 1 4
4

(swap! my-atom (fn [state] (* state 4)))
my-watcher #object[clojure.lang.Atom 0x673d073a {:status :ready, :val 16}] 4 16
16

; теперь уберем наблюдателя
(remove-watch my-atom "my-watcher")
#object[clojure.lang.Atom 0x673d073a {:status :ready, :val 16}]

(swap! my-atom inc)
17

Наблюдатели позволяют упростить процесс логгирования и отладки и сделать жизнь разработчика чуть легче, однако, никто не мешает добавить в функцию наблюдателя какие-либо внешние мутации (например, мутация другого ресурса), но лучше так не делать :)

Задание

Создайте атом (начальное значение 0) и добавьте к нему наблюдателя, который при изменении атома выводит сообщение (с помощью print) в следующем виде Change state from x to y., где x - прошлое состояние атома, а y - новое состояние атома. Затем дважды увеличьте атом на 1, потом уменьшите его значение на 1.


Нашли ошибку? Есть что добавить? Пулреквесты приветствуются https://github.com/hexlet-basics
Если вы столкнулись с трудностями и не знаете, что делать, задайте вопрос в нашем большом и дружном сообществе