6
votes

My question is about nested map's/key's in a clojure atom and how to update them at the same time. In my case I have a nested map in another map wich is a state holding atom of a little game.

This is my atom:

(def state (atom {:mousePos {:x 0 :y 0}
                  :playArea {:width 10000 :height 10000}
                  :player {:zoomOut 7.5
                           :cells [{:center {:x 1234 :y 5678}
                                    :radius 17.84124116
                                    :area 1000}]
                           :gravityCenter {:x 1234 :y 5678}
                           :gravityRadius 17.84124116}}))

And in this atom i want to update the mousePos x and y values at the same time to ensure their consistency/concurrency.

At the moment i'm doing:

(swap! state assoc-in [:mousePos :x] mouseX)
(swap! state assoc-in [:mousePos :y] mouseY)

But those are two swap!'s and theoretically if the thread where to switch in between i could end up with the problem, that for the following operations in the other thread, i would use the current x but the old y position of the mouse and i don't want that.

So i hoped to do something like this:

(swap! state assoc-in [:mousePos :x] mouseX
                      [:mousePos :y] mouseY)

Witch of course will not work so i tried writing my own assoc-in-mult function and that is where i'm unsuccessfull.

1
I suggest you rephrase your title to describe your "Actual question", and put that at the top. The old post may be interesting for reference, but is not strictly necessary. Can you provide a link to it instead? If you already deleted it, you could undo the delete and answer it yourself.Toni Vanhala
also use :mouse-pos Clojure convention instead of :mousePosErtuğrul Çetin
Possible duplicate of Debugging in Clojure?Sam Estep
Please do not ask two unrelated questions in a single question. If you want to know two things, ask two questions. I have edited your question to be just the "original" question; I suggest you take your answer to that question (which you can get from the edit history), and post it as an actual answer to your question (by pressing the "Answer your question" button at the bottom of the page), then ask a new, separate question about the debugging.amalloy

1 Answers

5
votes

When assoc-in doesn't fit with your use pattern because like you have here you want to update more than one value, then the more generic update-in or update functions tend to work well.

user> (def state (atom {:mousePos {:x 0 :y 0}}))
#'user/state
user> (swap! state update-in [:mousePos] assoc :x 123 :y 321)
{:mousePos {:x 123, :y 321}}

or when you have just one kay in the update path:

user> (swap! state update :mousePos assoc :x 123 :y 321)
{:mousePos {:x 123, :y 321}}