I'm going to be "that" guy and ask... why actors? Why not agents?
The concept of agents (as defined by Rich Hickey in a lot of his Clojure talks) is all about a globally shared, immutable and persistent state on which you can act upon.
With actors you still need to have the actor handle its own mailbox of requests and then handle them, the actor has to define its behavior.
With agents you don't have to ask for the world to stop to communicate, you can read the current snapshot of the world (aka no request to view the state, no database queries) and send transformation functions on the data of that specific agent, which will be then processed by the agent's thread in an ordered way.
I'd love to see more insight on the choice for this, it's interesting as I am currently working on a similar project.
> I'm going to be "that" guy and ask... why actors? Why not agents?
Because actor is an establish paradigm and that has been around for a while. I haven't heard Hickey's talk on "agents" but based on your description, how are agents radically different?
What stops actors from reading the snapshots of the world? They can 1) subscribe to "world" actor and get publication when it changes or 2) if database is immutable (I guess you are hinting at Datomic or Clojure's datastructures here?) an actor can also call a function. Remember actors in practice are there to help isolate concurrency contexts. Reading truly immutable data is safe so actors could just periodically read this immutable data (just think of the database a function). It would be awkward having to process messages from mailbox, timing out, then reading world state, process world state, going back to processing messages. Etc. I like 1) better.
> the actor has to define its behavior.
How does an agent bypass defining its behavior? Doesn't an agent have a piece of code that specifies what that agent does.
> and send transformation functions on the data of that specific agent, which will be then processed by the agent's thread in an ordered way.
So this basically centralizes the state of all the agents in one central location that is an immutable database? Hmm interesting. It is a different way of looking it at it I guess. Each actor usually handles its own internal state privately. I guess we also assume that there is something underneath that constantly distributes all these incrementing tree of states across a whole system. I don't know I would rather think of actors explicitly choosing to send their state to a system half way across the world rather than rely on another layer of distributing state. Maybe it is just a matter of a mental model here...
The substantial difference is that actors act on messages while agents are only pieces of data with an assigned thread (in a pool, doesn't matter) that is scheduled to retrieve the functions passed via send and send-off. There is an amazing talk from Rich about clojure concurrency where he implements an ant simulation with agents, it's really great. He also mentions the difference between the erlang and the clojure model in a much better way than I possibly would.
Actually, the biggest thing Quasar gives you is lightweight threads. That's the hard part. Building actors, agents or dataflow variables on top of that is very easy.
Having said that, I do think actors have some advantages over agents when it comes to fault tolerance. Actors better isolate and communicate faults.
Yes, you are entirely correct, my point about actors vs agents was only taking in consideration a shared memory situation (only one local multicore processor), in case of a distributed system with multiple nodes located on different memory spaces and machines the erlang approach is much superior, especially for actor discovery, monitoring (ie heartbeat) and fault tolerance in general.
The concept of agents (as defined by Rich Hickey in a lot of his Clojure talks) is all about a globally shared, immutable and persistent state on which you can act upon.
With actors you still need to have the actor handle its own mailbox of requests and then handle them, the actor has to define its behavior.
With agents you don't have to ask for the world to stop to communicate, you can read the current snapshot of the world (aka no request to view the state, no database queries) and send transformation functions on the data of that specific agent, which will be then processed by the agent's thread in an ordered way.
I'd love to see more insight on the choice for this, it's interesting as I am currently working on a similar project.