Feel free to correct my history, but as far as I understand it, Rx and the Reactive Manifesto trace their roots back to C# and its Reactive Extensions, which is uses push (callback-based) messaging, so that Publishers call Subscriber methods with values, rather than returning values to a subscribing scope like an iterator. This is a bit surprising, seeing as C# has very mature and strong iterator mechanics like LINQ, not to mention it birthed await-async, which is distinctly pull.
I'm designing a Reactive Library in Hacklang, and while for the question of which style is more fundamental, the message-driven camp might have it — you could say that CPS is message-driven, or that the scheduler is really a message relay, and I could see your point — I don't really see the benefit.
Hack tightly embraces the async-await model. One consequence is that pushing messages asynchronously is actually exceptionally difficult. Almost all asynchronous objects are designed to be
awaited and produce a value dependency, so it is hard for any code to set and forget a callback that it doesn't depend on.
However, it has actually been a joy to program with iterators, not a hindrance. At its core is the
AsyncGenerator, which comes from yielding [read: lazy] async functions. They are iterated by a foreach-like construct (
await as), so that means the "subscriber" or calling scope can
break out whenever it wants, ask for elements whenever it wants,
throw, return its own pending values, become an iterator — anything the language allows synchronous code to do. This level of subscriber freedom, especially requesting elements at will sounds like the direction Reactive Streams is going, which is indicative to the problems it solves. With iterators, though, it's baked-in from the start.
Returning to C#, with its already impressive suite of iterator mechanics, why did it opt for callbacks for Reactive Extensions? Did their decision set the stage for the push to dominate? Is there a distinct performant, familiar, expressive, etc. reason for the prevalence of push messaging in Reactive?
Edit: Ah, InteractiveX was the name of the concept I was looking for: replacing
IEnumerable. It is indeed more obscure — the ReactiveX organization only publishes a JS implementation — and if I understand Bart de Smet's presentation about Ix back in 2011, some operators aren't implemented "interactively" even, but rather are achieved by converting to
IQueryable, building the expression tree, and back to
IEnumerable to iterate.
Maybe due to equivalence, just one of ReactiveX vs. InteractiveX was good enough? Maybe it is unnatural to work with? Bart de Smet mentions the
ISubject <-> IBuffer dual, which I found enlightening. There isn't much documentation outside of his talk which doesn't discuss much about the motivations, so I'm still taking shots in the dark a bit.