Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure states within states within states

I'd love to hear what advice the Clojure gurus here have about managing state in hierarchies. I find I'm often using {:structures {:like {:this {:with {:many 'levels}} } } } and if I want to track changes in state at multiple levels, by throwing atoms around values (atom {:like (atom 'this)} ), I find myself thinking this must be wrong. Is it generally better to use just one atom at the top level, and have none as values in a map ?

like image 312
Hendekagon Avatar asked Nov 14 '11 04:11

Hendekagon


1 Answers

Don't use nested atoms in a data structure if at all possible.

The main reason is that immutability is your friend. Clojure is a functional language that thrives on immutable data structures. Most libraries assume immutable data structures. Clojure's STM assumes immutable data structures to get the best possible concurrency. Immutability gives you the opportunity to take consistent snapshots of the entire state at any one instant. Pure functions that operate on immutable data are easy to develop and test.

If you put atoms inside your data structures then you lose all the advantages of immutability and risk making your code very complex - it's a lot harder to reason about a data structure if it contains a lot of mutable components.

Some suggested alternative approaches:

  • Put your entire data structure in a single ref or atom. This can be a huge data structure with no problem - I once wrote a game where the entire game map was held in a single atom without any difficulty.
  • Use the various methods that are designed for accessing and changing nested immutable data structures: assoc-in, get-in, update-in etc.
  • Use recursive functions to make navigating your data structure more managable. If one node of your structure has sub-nodes of the same "type" then it's usually a good hint that you should be using some form of recursive function.
like image 171
mikera Avatar answered Sep 18 '22 16:09

mikera