The documentation for ref shows a :max-history option and states that “refs accumulate history dynamically as needed to deal with read demands.” I can see that there is history at the REPL, but I don’t see how to find previous values of a ref:
user=> (def the-world (ref "hello" :min-history 10))
#'user/the-world
user=> (do
(dosync (ref-set the-world "better"))
@the-world)
"better"
user=> (let [exclamator (fn [x] (str x "!"))]
(dosync
(alter the-world exclamator)
(alter the-world exclamator)
(alter the-world exclamator))
@the-world)
"better!!!"
user=> (ref-history-count the-world)
2
Presumably the-world has had the values “hello”, “better”, and “better!!!”. How do I access that history?
If it is not possible to access that history, is there a datatype that keeps a history of its values that can be queried afterwards? Or is that why the datomic database was created?
0
I believe :min-history and :max-history only refer the history of a ref during a transaction.
However, here’s a way to do it with an atom and a watcher:
user> (def the-world (ref "hello"))
#'user/the-world
user> (def history-of-the-world (atom [@the-world]))
#'user/history-of-the-world
user> history-of-the-world
#<Atom@6ef167bb: ["hello"]>
user> (add-watch the-world :historian
(fn [key world-ref old-state new-state]
(if (not= old-state new-state)
(swap! history-of-the-world conj new-state))))
#<Ref@47a2101a: "hello">
user> (do
(dosync (ref-set the-world "better"))
@the-world)
"better"
user> (let [exclamator (fn [x] (str x "!"))]
(dosync
(alter the-world exclamator)
(alter the-world exclamator)
(alter the-world exclamator))
@the-world)
"better!!!"
user> @history-of-the-world
["hello" "better" "better!!!"]
1