Interesting thought! I implemented propagators some years ago (sometime soon after seeing Alexy Radul speak at a Lisp conference at MIT ~2009?). My implementation was mostly a direct port, but I used Clojure's agents to maintain propagator state.
If you use Clojure's transactional memory, then you'll end up using refs for propagators (refs are the only reference type that directly participates in transactions). In terms of tracking the changes to each ref, watches (see
add-watch) will do the job. Note, however, that watches will be notified only once for a change in a ref's value in a transaction; the ref's
in-transaction value may have changed multiple times, but those "events" don't escape into the world outside of the transaction.
Good luck! By all means, post to the main Clojure mailing list with a link to your implementation. :-)
--
(coauthor of
Clojure Programming from O'Reilly; creator of
Clojure Atlas)