Как посмотреть подмножество дерева clojure (Hash Map) на предмет изменений? - PullRequest
3 голосов
/ 02 января 2011

Я хотел бы наблюдать за изменениями в различных частях карты Clojure Hash (доступ к которой осуществляется через ссылку STM), которая образует довольно большое дерево, и об изменениях в этих частях я хотел бы вызвать некоторых зарегистрированных слушателей. Как я могу сделать это в ближайшем будущем, поскольку я понимаю, что «add-watch» работает только для всей ссылки?

Ответы [ 3 ]

2 голосов
/ 02 января 2011

Поскольку карты Clojure являются неизменяемыми, на самом деле не существует такой вещи, как изменение одной части дерева с концептуальной точки зрения.

Однако я вижу несколько хороших вариантов:

  • Добавьте часы ко всему дереву, но проверьте, изменилась ли интересующая вас деталь.Это должно быть довольно быстро и легко проверить (используйте «get-in» для поиска правой части дерева)
  • Маршалл все изменения в дереве через библиотеку вспомогательных функций, которые могут перехватывать видинтересующих вас изменений.
1 голос
/ 05 марта 2011

Я бы тоже посмотрел все дерево и проверил подмножества с помощью get-in. Вы можете быстро проверить, было ли изменено поддерево, используя идентичное? проверить против предыдущего состояния. Что-то вроде

(defn change-tester [tree path]
  (let [orig (get-in tree path)]
    (fn [tree]
      (not (identical? (get-in tree path) orig)))))

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

1 голос
/ 02 января 2011

Карты Clojure являются неизменяемыми, что означает, что они также являются поточно-ориентированными, что хорошо. Когда вы изменяете одно с помощью 'assoc' или аналогичного, вы создаете новую копию, в которой присутствуют ваши измененные значения. (Обратите внимание, что полная копия не сделана, но для ее создания используется эффективный метод.)

Я думаю, что, пожалуй, лучший способ сделать то, что вы хотите, это создать собственную структуру данных, потому что, по сути, вы запрашиваете изменяемый HashMap, как в Java, а не карту Clojure.

Вы можете создать оболочку вокруг существующего Java HashMap, которая переопределяет методы 'put' и 'putAll', чтобы вы могли обнаружить, что изменяется. Если у вас есть HashMap в HashMap, вы захотите, чтобы вспомогательная HashMap также имела новый тип, чтобы вы могли обнаруживать изменения на любом уровне.

Вы можете назвать это как «WatchfulHashMap». Затем вы захотите создать экземпляр этого нового HashMap, например:

(def m (ref (WatchfulHashMap.)))

Таким образом, делая один его экземпляр изменяемым из любой точки вашего приложения.

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