Continuous function in Clojure atom

I have a function that will load a lot of users (which will take a while) and store them in an atom. I'm wondering if there is a difference between loading the users into a let binding and then resetting the atom, or just loading them into a reset atom! function?

(let [all-users (get-users)]
    (reset! users all-users))

      

or

(reset! users (get-users))

      

+3


source to share


2 answers


They are the same and here's why

Since it reset!

is a function, the call (reset! users (get-users))

will behave like any other function call in Clojure: each of the S-expressions in the call will be evaluated and then passed as arguments to the function. This means that the evaluation will be performed first (get-users)

and the result passed to reset!

. This way it will behave exactly like the form does let

.

To contrast with swap!

If these problems come into play, it is swap!

. Since you are sending a swap!

function to be called inside a transaction, you have more control over whether your long running job is running inside or outside the transaction. For example, if you have functions poll-users-updates

and update-users-from-poll

, you can set up a call to the first function both inside and outside the transaction:

; outside the transaction
(swap! users update-users-from-poll (poll-users-updates))
; inside the transaction
(swap! users (fn [users] (update-users-from-poll users (poll-users-updates))))

      



The second form here will most likely need to be restarted, since the update function will take longer to complete and more time for another write to the atom will need to be restarted.

In contrast, the first form will be less likely to be forced to retry and is generally preferable. On the other hand, if your function is poll-users-updates

also needed to deal with the current state of the data users

(for example, to find the timestamp of the last updated user to make the survey more efficient) then the second approach may be preferable as it will ensure that you enter the most recent metric users

when conducting a survey.

With repeated attempts and side effects

What this highlights with regard to STM is that your update functions can be called multiple times. To say that side functions are "dangerous within atoms" is perhaps a little strong. They can be dangerous, although it is better to assume that they are. Even if it is not (for example, when the idempotent effects, that is, you get the same one word as you call it multiple times), it is better to keep them free of side effects. This is true for both Clojure refs and atoms, which are repeated in case of collisions. In contast, agents do not have retry semantics, so it is quite normal to have side effects in functions sent to agents. Since the agent queues the update functions and runs them in order, there is no chance of conflicts and therefore no need to try again.

+6


source


There reset!

will be no difference when used . However, you must be careful when using other functions that work with atoms, as functions that produce values ​​can be called multiple times. This is, for example, the case with swap!

.



+3


source







All Articles