Pattern: Atom of atoms - does it stink?

Hi all,
just thinking out loud - I have a scenario where I have a common “global” state (all calls on a PBX) but each call is handled by a “handler” that runs in a separate thread and receives async messages.
So I have two separate concerns: a “global” state - that is an atom - made up of multiple local states (separate calls) that I thought it would be easy to implement as separate atoms, as call handlers have no knowledge of the global state.
So I was wondering: is it a big smell - or a smell at all - if I implement a global “state” atom that contains separate atoms, one for each call that is to be updated asynchronously? or are there better ideas for a case like this?

1 Like

I’m not the right person to say whether this is a smell or not but I’ll say what I usually do.

I try to always avoid having more than one atom for similar things, this usually make things way easier.
For your case I’d probably use one single (atom {}) with entries representing the calls.

If you really fell like doing multiple small states and need coordination between them maybe it might be better to use refs. But for me a single atom solved all the problems I had up to this point

IMHO nested atoms are useless. The purpose of an atom is to let only one thread to update its data. That means there would be only one thread to update nested atoms. Which means nested atoms never have to actually do anything. A nested map works for this.
All you’ll achieve with nested atoms is to make updates harder syntactically due to nested swap! calls.


1 Like

I won’t use nested swap! calls - I will send a different thread a reference to the inner atom and it will update the atom as it sees fit, without even knowing that the inner atom is a part of an “outer” atom. This means that updating an inner or outer atom does not depend on other threads updating other atoms.

Ah, now I get what you’re trying to do. I still don’t see a use for nested atoms, only potential problems. For one my gut tells me that nested atoms are like objects, each with its own state holding references to one another. This hard to think about and hard to test. And not at all like FP.

Regarding processes that work independently: I’d try to make them pure, i.e. no global mutable state. Each process has its own data and passes it along until the calculation finished. The result is returned and incorporated into the single atom.
If processes can’t be pure I’d look into how state can be managed. It there is a supervising process for example, I’d use refs and software transactional memory. If the processes are more consumer/producer like, I’d use channels (core.async).