Hacker News new | ask | show | jobs
by chazu 4444 days ago
Can someone tell me the key differences between the actor model and reactive/dataflow programming? I haven't seen any references to erlang in conversations about Reactive programming, which seems odd to me as erlang's lack of shared state and message-passing seem like they fit the definition of reactive programming.
3 comments

As I understand it (and I may not understand it at all!), the most significant difference is that dataflow programming is deterministic and compositional, whereas actors are nondeterministic and discrete. Intuitively, I tend to compartmentalize dataflow along with maps, filters and comprehensions; and actors with FSMs. This is probably an incorrect generalization, but it works for me.

Somewhere, Hoare gives an example of pipelining the sieve of Eratosthenes through a series of communicating processes, which is a good example of dataflow programming -- you send a list of integers to a process that sieves out even numbers and sends the result to a process that sieves out multiples of 3, and so on. Such a pipeline is deterministic -- given a set of values, you will always get the same output -- and compositional -- the sum of the sieves is greater than the individual parts.

A traditional actor-based model, on the other hand, isn't well-suited for that kind of problem, but is great if your goal is to dispense biscuits and chocolates. State is kept locally, and the actor can change its behavior to external messages based on internal state -- that is to say, actors have discrete identities. The response to any particular message is nondeterministic, because it depends on what's the actor's internal state and decision process may be, and you can't really combine multiple vending machines to compose a new, super-vendor.

I think the key difference is in which side of the conversation between transmitter and receiver the intentionality is vested.

- Actors have no control over where messages come from. Actors have complete control over what other actors receive their messages.

- In a reactive model, a producer sends messages blindly, with no control over the receiver. The consumer chooses its sources specifically.

I'm not sure if this is exactly the right answer, but it is the impression I got after reading a paper on dataflow programming [1]. I'd be interested in whether anyone has any deep insights on the relative advantages of each model, and whether they're actually equivalent on some level.

[1] http://infoscience.epfl.ch/record/176887/files/DeprecatingOb...

They're basically unrelated. The actor paradigm is basically imperative programming, with boundaries being put up between the actors, and the way you cross the boundary is with a message. If that sounds too foreign, bear in mind that while OO doesn't have to be an "Actor" and an actor doesn't have to be "OO", they share a certain structural similarity, in that one of the primary characteristics of working with an "object oriented" system is that you are creating imperative islands of code, and the way you cross the barriers are via method calls. Indeed back when OO was first being formulated you can see the terminology was not settled yet, and you'll see method calls being called "messages" even today in some OO communities.

The Actor model is basically OO, except that objects are given their own execution contexts, whereas in OO there's one execution context that drives the objects. You can do worse for your first design in Erlang than to break your task into core objects exactly as you would for a high-level OO design (don't put in all the little collection and iterator and other structure classes, stick to the "high level" design), and use that to drive your process design. It won't be perfect, but it's not a bad first pass. The profound differences between one execution context and multiple also has subsequent follow-on effects on the languages in question, and in what direction they evolve, so in practice they feel quite different despite the underlying similarities in the model.

Reactive programming is extremely different. There, values are defined as functions on other values, intrinsically, such that if A is B + C, future changes to B and C mean that A is automatically updated to the new B + C with no programmer interaction. This is no longer imperative design; instead of your program consisting of a huge set of instructions for the processor to directly execute (no matter how gussied up that is by the syntax and semantics of the local language), your program consists of a declaration of relationships between values and how they evolve over time. The fundamental operation of the programming language is no longer "Set value identified by X to Y", but "Attach value X to value Y with update function Z".

As is always the case in the world of Turing Completeness, this can be embedded into OO, or OO can be embedded into it, etc. all sorts of combinations are possible. But it is a fundamentally different underlying method for writing your program.

I would observe that A: this isn't new, which I say not because anyone is claiming that it is but because it means that we can in fact draw on past experience to examine it and B: our general experience with it up to this point is that it often makes small tasks easier, even much easier, but that trying to create whole systems this way is often quite problematic. If you think laziness in Haskell is hard to understand, just wait until you're trying to understand a cyclic dependency graph in a data-binding environment (the usual OO manifestation) or a spreadsheet, with the local bizarre adaptations to try to make that sensible all interacting with each other in crazy complicated ways. It's a useful tool, and I don't mean that as a mere rhetorical sop, it really is a useful tool to have in the belt, but I'm deeply skeptical of it as a proclaimed savior of programming, or the Next Big Paradigm. Our experiences with it up to this point have not been positive enough to justify that claim, IMHO, and I haven't seen that there's been any sort of big enough change in the landscape lately to justify that.

Compare to "functional programming", which has been the Next Big Paradigm for a few decades now, but IMHO modern Haskell of the past 3-5 years really is a big enough advance to justify some examination on the topic. (I'm not saying Haskell is guaranteed to be the Next Big Thing, I'm just saying that there's been enough action there to legitimately justify having a fresh look at the situation.)

If you can point me at the big advance for reactive programming in question, I'd love to have a look. I know the Haskell world has been fiddling with FRP but I'm still underwhelmed by the efforts.

> just wait until you're trying to understand a cyclic dependency graph in a data-binding environment (the usual OO manifestation) or a spreadsheet, with the local bizarre adaptations to try to make that sensible all interacting with each other in crazy complicated ways.

I think that may be a significant, fundamental problem with reactive programming. The way these graphs are constructed is typically (necessarily?) buried within the reactive programming framework, giving the programmer poor visibility into what's actually happening. Maybe that problem can be solved, but I suspect it might be intrinsic to reactive programming.

> I know the Haskell world has been fiddling with FRP but I'm still underwhelmed by the efforts.

I've test-driven some of those projects. Last I checked, the documentation was extremely sparse, and the only examples were trivial. I haven't yet seen an example of a useful Haskell app built with FRP. FRP has sometimes been described as the silver bullet for doing stateful apps in a pure FP way. Maybe it is, but for now, I'm sticking with pseudo-imperative Haskell for those purposes.