Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple assoc-in's in one swap! operation eg. to update x, y of point at the same time

Tags:

state

clojure

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.

like image 203
Andimanos Avatar asked Aug 03 '17 12:08

Andimanos


1 Answers

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}}
like image 165
Arthur Ulfeldt Avatar answered Oct 23 '22 04:10

Arthur Ulfeldt