Call a side effecting function only when atom value changes - clojure

What is the simplest way to trigger a side-effecting function to be called only when an atom's value changes?
If I were using a ref, I think I could just do this:
(defn transform-item [x] ...)
(defn do-side-effect-on-change [] nil)
(def my-ref (ref ...))
(when (dosync (let [old-value #my-ref
_ (alter! my-ref transform-item)
new-value #my-ref]
(not= old-value new-value)))
(do-side-effect-on-change))
But this seems seems a bit roundabout, since I'm using a ref even though I am not trying to coordinate changes across multiple refs. Essentially I am using it just to conveniently access the old and new value within a successful transaction.
I feel like I should be able to use an atom instead. Is there a solution simpler than this?
(def my-atom (atom ...))
(let [watch-key ::side-effect-watch
watch-fn (fn [_ _ old-value new-value]
(when (not= old-value new-value)
(do-side-effect-on-change)))]
(add-watch my-atom watch-key watch-fn)
(swap! my-atom transform-item)
(remove-watch watch-key))
This also seems roundabout, because I am adding and removing the watch around every call to swap!. But I need this, because I don't want a watch hanging around that causes the side-effecting function to be triggered when other code modifies the atom.
It is important that the side-effecting function be called exactly once per mutation to the atom, and only when the transform function transform-item actually returns a new value. Sometimes it will return the old value, yielding new change.

(when (not= #a (swap! a transform))
(do-side-effect))
But you should be very clear about what concurrency semantics you need. For example another thread may modify the atom between reading it and swapping it:
a = 1
Thread 1 reads a as 1
Thread 2 modifies a to 2
Thread 1 swaps a from 2 to 2
Thread 1 determines 1 != 2 and calls do-side-effect
It is not clear to me from the question whether this is desirable or not desirable. If you do not want this behavior, then an atom just will not do the job unless you introduce concurrency control with a lock.
Seeing as you started with a ref and asked about an atom, I think you have probably given some thought to concurrency already. It seems like from your description the ref approach is better:
(when (dosync (not= #r (alter r transform))
(do-side-effect))
Is there a reason you don't like your ref solution?
If the answer is "because I don't have concurrency" Then I would encourage you to use a ref anyway. There isn't really a downside to it, and it makes your semantics explicit. IMO programs tend to grow and to a point where concurrency exists, and Clojure is really great at being explicit about what should happen when it exists. (For example oh I'm just calculating stuff, oh I'm just exposing this stuff as a web service now, oh now I'm concurrent).
In any case, bear in mind that functions like alter and swap! return the value, so you can make use of this for concise expressions.

I'm running into the same situation and just come up 2 solutions.
state field :changed?
Keeping a meanless :changed mark in atom to track swap function. And take the return value of swap! to see if things changed. For example:
(defn data (atom {:value 0 :changed? false}))
(let [{changed? :changed?} (swap! data (fn [data] (if (change?)
{:value 1 :changed? true}
{:value 0 :change? false})))]
(when changed? (do-your-task)))
exception based
You can throw an Exception in swap function, and catch it outside:
(try
(swap! data (fn [d] (if (changed?) d2 (ex-info "unchanged" {})))
(do-your-task)
(catch Exception _
))

Related

Understanding STM properties in Clojure

I'm going through the book 7 concurrency models in 7 weeks. In it philosophers are represented as a number of ref's:
(def philosophers (into [] (repeatedly 5 #(ref :thinking))))
The state of each philosopher is flipped between :thinking and :eating using dosync transactions to ensure consistency.
Now I want to have a thread that outputs current status, so that I can be sure that the state is valid at all times:
(defn status-thread []
(Thread.
#(while true
(dosync
(println (map (fn [p] #p) philosophers))
(Thread/sleep 100)))))
We use multiple # to read values of each philosopher. It can happen that some refs are changed as we map over philosophers. Would it cause us to print inconsistent state although we don't have one?
I'm aware that Clojure uses MVCC to implement STM, but I'm not sure that I apply it correctly.
My transaction contains side effects and generally they should not appear inside a transaction. But in this case, transaction will always succeed and side effect should take place only once. Is it acceptable?
Your transaction doesn't really need a side effect, and if you scale the problem up enough I believe the transaction could fail for lack of history and retry the side effect if there's a lot of writing going on. I think the more appropriate way here would be to pull the dosync closer in. The transaction should be a pure, side-effect free fact finding mission. Once that has resulted in a value, you are then free to perform side effects with it without affecting the STM.
(defn status-thread []
(-> #(while true
(println (dosync (mapv deref philosophers)))
(Thread/sleep 100))
Thread.
.start)) ;;Threw in starting of the thread for my own testing
A few things I want to mention here:
# is a reader macro for the deref fn, so (fn [p] #p) is equivalent to just deref.
You should avoid laziness within transactions as some of the lazy values may be evaluated outside the context of the dosync or not at all. For mappings that means you can use e.g. doall, or like here just the eagerly evaluated mapv variant that makes a vector rather than a sequence.
This contingency was included in the STM design.
This problem is explicitly solved by combining agents with refs. refs guarantee that all messages set to agents in a transaction are sent exactly once and they are only sent when the transaction commits. If the transaction is retried then they will be dropped and not sent. When the transaction does eventually get through they will be sent at the moment the transaction commits.
(def watcher (agent nil))
(defn status-thread []
(future
(while true
(dosync
(send watcher (fn [_] (println (map (fn [p] #p) philosophers))))
(Thread/sleep 100)))))
The STM guarantees that your transaction will not be committed if the refs you deref during the transaction where changes in an incompatible way while it was running. You don't need to explicitly worry about derefing multiple refs in a transaction (that what the STM was made for)

Creating refs with transducers

Is it possible to create a ref with a transducer in Clojure, in a way analogous to creating a chan with a transducer?
i.e., when you create a chan with a transducer, it filters/maps all the inputs into the outputs.
I'd expect there's also a way to create a ref such that whatever you set, it can either ignore or modify the input. Is this possible to do?
Adding a transducer to a channel modifies the contents as they pass through, which is roughly analogous to adding a watch to a ref that applies it's own change each time the value changes. This change it's self then triggers the watch again so be careful not to blow the stack if they are recursive.
user> (def r (ref 0))
#'user/r
user> (add-watch r :label
(fn [label the-ref old-state new-state]
(println "adding that little something extra")
(if (< old-state 10) (dosync (commute the-ref inc)))))
#<Ref#1af618c2: 0>
user> (dosync (alter r inc))
adding that little something extra
adding that little something extra
adding that little something extra
adding that little something extra
adding that little something extra
adding that little something extra
adding that little something extra
adding that little something extra
adding that little something extra
adding that little something extra
adding that little something extra
1
user> #r
11
You could even apply a transducer to the state of the atom if you wanted.
This is an interesting idea, but the wrong way to go about it for at least a couple reasons. You'd lose some relationships you'd expect to hold:
(alter r identity) =/= r
(alter r f)(alter r f) =/= (alter r (comp f f))
(alter r f) =/= (ref-set r (f #r))
Also some transducers are side-effecting volatiles, and have no business in a dosync block. i.e. if you use (take n) as your transducer then if your dosync fails, then it'll retry as though invoked with (take (dec n)), which violates dosync body requirements.
The problem is a ref lets you read and write as separate steps. If instead there was something foundational that let you "apply" an input to a hidden "state" and collect the output all in one step, consistently with the STM, then that'd be something to work with.

Idiomatic no-op/"pass"

What's the (most) idiomatic Clojure representation of no-op? I.e.,
(def r (ref {}))
...
(let [der #r]
(match [(:a der) (:b der)]
[nil nil] (do (fill-in-a) (fill-in-b))
[_ nil] (fill-in-b)
[nil _] (fill-in-a)
[_ _] ????))
Python has pass. What should I be using in Clojure?
ETA: I ask mostly because I've run into places (cond, e.g.) where not supplying anything causes an error. I realize that "most" of the time, an equivalent of pass isn't needed, but when it is, I'd like to know what's the most Clojuric.
I see the keyword :default used in cases like this fairly commonly.
It has the nice property of being recognizable in the output and or logs. This way when you see a log line like: "process completed :default" it's obvious that nothing actually ran. This takes advantage of the fact that keywords are truthy in Clojure so the default will be counted as a success.
There are no "statements" in Clojure, but there are an infinite number of ways to "do nothing". An empty do block (do), literally indicates that one is "doing nothing" and evaluates to nil. Also, I agree with the comment that the question itself indicates that you are not using Clojure in an idiomatic way, regardless of this specific stylistic question.
The most analogous thing that I can think of in Clojure to a "statement that does nothing" from imperative programming would be a function that does nothing. There are a couple of built-ins that can help you here: identity is a single-arg function that simply returns its argument, and constantly is a higher-order function that accepts a value, and returns a function that will accept any number of arguments and return that value. Both are useful as placeholders in situations where you need to pass a function but don't want that function to actually do much of anything. A simple example:
(defn twizzle [x]
(let [f (cond (even? x) (partial * 4)
(= 0 (rem x 3)) (partial + 2)
:else identity)]
(f (inc x))))
Rewriting this function to "do nothing" in the default case, while possible, would require an awkward rewrite without the use of identity.

Editing running program with infinite loop

In this (http://vimeo.com/14709925) video dude edits running program that renders opengl stuff in a loop.
When i run this:
(def a 10)
(defn myloop
[]
(while (= 1 1)
(println a)
(Thread/sleep 1000)))
(myloop)
then change value of a, re eval does nothing, value doesn't seem to change. I'm using LightTable IDE. Should i switch to emacs?
One possibility is that the re-evaluation isn't taking place because it is done on the same thread as the running program. Try running myloop in another thread instead with (future (myloop)) instead of (myloop) and then re-def your a after a few prints and see if it changes.
Note that (in current Clojure versions) all vars are dereferenced each time they are encountered, which allows for this dynamic behavior, but re-def-ing except during interactive testing/experimentation/demonstration is frowned upon. See atoms and refs.
Another consequence of this behavior of vars is that dereferencing can impact the efficiency of performance critical tight loops. Where the dynamic behavior is not needed you might see the following idiom to capture the value first (note you shouldn't attempt pre-optimazation in general until bottlenecks are identified).
(def foo 42)
(let [foo foo] ; capture value of foo within scope of let
(loop ...
; do something with value of foo captured before entering loop
... ))
I know this isn't a direct answer to your question - but if you want to mutate state in this way in Clojure, I think it is probably more idiomatic to use one of the constructs for state manipulation (for example, an atom) rather than re-evaluating a def.
This is especially true if you're likely to need multiple threads, which might well be the case if you're working with graphics.
(def a (atom 10))
(defn myloop []
(while (= 1 1)
(println #a)
(Thread/sleep 1000)))
(myloop)
(reset! a 9)

Clojure idiomatic get-and-set function

Is there a more idiomatic/readable way of writing a get-and-set function in Clojure than:
(def the-ref (ref {}))
(defn get-and-set [new-value]
(dosync
(let [old-value #the-ref]
(do
(ref-set the-ref new-value)
old-value))))
for the simple cases I tend to see this operation used directly instead of wrapped in a function:
hello.core> (dosync (some-work #the-ref) (ref-set the-ref 5))
5
In this case dosync generally serves as the wrapper you are looking for. within the dosync This is significant because dosync composes nicely with other transactions and makes the bounds of the transaction visible. If you are in a position where the wrapper function can completely encapsulate all the references to the ref then perhaps refs are not the best tool.
A typical use of refs could look more along these lines:
(dosync (some-work #the-ref #the-other-ref) (ref-set the-ref #the-other-ref))
The need to wrap it is rare because when ref's are used they typically are use in groups of more than one ref because coordinated changes are required by the problem at hand. In cases where their is just one value then atoms are more common.