In Hewitt's actor model, messages are also (immutable) actors. At least in the early version I read about.
previous important contributions including lambda calculus
[Church 1932] (first-class procedures), Petri nets [Petri
1962] (true concurrency), semaphores [Dijkstra 1962-1963],
packet switching [Baran 1964] (concurrent communication
between computers using fixed size packets), capabilities
[Dennis and van Horn 1966] (pointer security), Simula [Dahl
and Nygaard 1967] (class hierarchy), and SmallTalk-72
[Goldberg and Kay 1976] (bit-mapped computer graphics and
browser, the precursor of modern programming Integrated
Development Environments). The lambda calculus could not
express concurrency with the consequence that lambda
calculus programs can be thousands of times slower than
Actors. A Petri net cannot dynamically expand and has the
limitation that tokens can miraculously disappear from
different places, which is inefficient to implement.
Capabilities have the limitation that pointers must be
manipulated using indexes into capability lists thereby
making programming awkward. Simula did not implement
concurrency and did not have messages. SmallTalk-72 used a
byte stream of program tokens thereby making it awkward for
concurrency.
See the following for more information: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3418003
The monad (https://wiki.haskell.org/Monad) is another mostly unsuccessful lambda calculus way to try to address some of the issues resolved in the Actor Model.
I only knew about actors for its scheme influence and the fact that it was highly concurrent (even this I'm not so sure). I got into college way too late for it to be studied sadly.
> As Erlang became popular we were often asked "Is Erlang OO" - well, of course the true answer was "No of course not" - but we didn't to say this out loud - so we invented a serious of ingenious ways of answering the question that were designed to give the impression that Erlang was (sort of) OO (If you waved your hands a lot) but not really (If you listened to what we actually said, and read the small print carefully).
Oof.
So I would qualify 'best' to meant "easiest system that 95% looks like actors that you can quickly get up and running and doing useful things and or play around with"
Satisfactory implementation for Reusable Scalable Intelligent Systems with millions of Actor cores for quadrillions of Actor are under development, but not yet publicly available.
I deployed an actor-based system model to completely rearchitect and replace an inefficient stateless python system. There have been zero runtime or concurrency errors since I deployed (unfortunately sometimes the hardware the actors are modeling fail us) but patches to work around the hardware failures are simple.
•Automatically reclamation of storage of an unreachable future [Baker and Hewitt 1977] (e.g. process in Erlang). For example, an Erlang process can be orphaned if its Process Identifier (PID) becomes inaccessible. Also, since Erlang is not strongly typed, cyberattacks can be launched against dangling references to processes that no longer exist.
•Language support for holes in the region of mutual exclusion of an Actor implementation. For example, in Erlang it is necessary for application programmers to explicitly code a message handler for each re-entry into the region of mutual exclusion potentially enabling cyberattacks from outside the process.
For example, if process X on node A sends a message to process Y on node B and the network goes down, that doesn't mean process Y won't send a message to process X when the network resume.
You have made the point exactly. The problem of dangling processes is made worse by the fact that Erlang is not strongly typed.
Especially objects that need to be pinned by ref counting.
My personal interpretation of the Actor model is a message passing system to model the real world.
In the real world I can shout out "make me a sandwich" and even if I perceive that there is a process that could potentially satisfy that request, I also work on the assumption that for any number of reasons... the channel of communication going away, misenterpretation, the agent or myself dying, the resources not being available or delays due to manufacturing may impede progress.
That is just the way the real world works.
Although Future/Promise can be built easily on top of Actor, they are optimistic at best - especially in diatributed cases; which, if my interpretation is correct is your reason for Actor in the first place.
Actor is powerful so in my opinion, future/promise and building ref-counts on top undermines the core of it.
Pat Helland, after numerous years of distributed transaction work completely did a 180 in the face of reality.
There is nothing wrong with Actor.
As far as strong typing, I personally believe that is a completely orthogonal conversation. I just cannot see the conflation.
Strongly typed to me means I send an argument to a function and it happens to match the signature.
Well, if I have a strongly typed function that takes two integers and somehow is supposed to return the sum. I guess it is helpful to know that as the user-agent (caller) of the function, but that knowledge only helps programmers, not computers.
Strong typing is definitely not a model of reality when dealing with humans as functions, and often humans are end-point "processes" (heh) of function calls.
Not that I am against strong typing in any way. I just believe the Actor model is cleaner without mixing things up.
Certainly agree Erlang is great but not the ultimate.
Well... my 2c and thanks to you, Alan, Joe, Hoare, Sussman, Gelernter et al. et al. for the inspirations over the years, and appreciate you plugging away at the models to this day.
Have a wonderful holiday.
edit : i misread your post, thought you were designing a system, not a PL... maybe you can still answer my question ?
In my experience with Elixir there are never many processes that have a state to save in a database. Eventually it's the same load no matter if the implementation is actor based or object oriented.
The general idea is to build the transaction in a pipeline of function calls. Each function gets the old definition of the transaction as an argument and returns a new one. Eventually the call at the end of the pipeline executes the statements in the definition, wrapping them in a transaction.
If the question is how to deal with 100 or 100 k concurrent transactions, the answer again is in the same way a cluster of servers running programs written in any other language do. Eventually SQL is SQL.
I think i’m still not clear on how you would design a transactional system ( such as order & paiement processing ) with actors in a way that won’t make it look like a microservice based system ( aka : one per subtask, fetching info from a db for each incoming request, and storing the result in a db in the end)
It seemed to me actors had to have a more fine grained context ( such as one per order), but in that case i’m wondering how it’s supposed to handle saving its state regularely so that no information on the order processing state is ever lost
I've never heard of an actor system able to automatically respawn actors with their previous state (the whole system would look like a tree of cached data, each layer responsible for saving the leafs under it, with a huge "persist to DB" on top , wouldn't it ?). Does erlang OTP do those kind of things ?
Edit: also, are you Prof "Carl" Hewitt ? The one that invented actors ? I'd be honored you found a question of mine about actors excellent...
The key insight is that an actor is a tiny VM and you just need to make the VM state durable.
- not all states transitions need to be durable. If performance matters you’ll have to get your actors to call something like a « saveState » from time to time, otherwise every single property change is going to have an overhead in terms of performance.
- what does « durable » mean ? Surely, just having the state of an actor saved in the memory of the supervisor isn’t enough. If the two are on the same server and the server shuts down, it’s game over. You need a « persistence » service / actor, but that thing is going to have to persist the state of all the actors in your system. I don’t see how that can work if you’ve got millions of actors running in parallel.
https://en.wikipedia.org/wiki/Oracle_machine
https://arstechnica.com/tech-policy/2019/11/supreme-court-wi...
(In the cover photo of that article, it looks like people have been urinating on the Oracle logo!)