But when it is, the .mergeMap() will still cause a side-effect, not the edge of the system.
Of course the whole thing isn’t triggered until the main observable is observed.
Luca Matteis

mergeMap does not cause a side effect. It creates a new stream that generates and observes other streams. Those other streams, when observed themselves, cause side effects, but those streams aren’t generated or observed or produce side effects until the main stream is observed itself. All of the side effects are generated as a result of the side effect of consuming the stream in the first place. The side effect does not literally occur in the middle of the Epic function.

Both redux-observable and Cycle.js do this; RO recommends producing side effects by consuming the stream directly rather than using the values emitted by the stream to produce side effects. Both have advantages & disadvantages; both are pure, declarative functions.

To me this is really the main difference. If you have grey boxes midway, you’re essentially not pushing side-effects to the edges, making your functions imperative.

Declarative programming does not mean “push side effects to the edges.” All the wikipedia quotes you cited are primarily properties of languages that are declarative, not definitions of what declarative is. That’s this line alone:

In computer science, declarative programming is a programming paradigm — a style of building the structure and elements of computer programs — that expresses the logic of a computation without describing its control flow.[1]

I would also cite this answer from StackOverflow:

The only attribute that can possibly differentiate a declarative expression from an imperative expression is the referential transparency (RT) of its sub-expressions. All other attributes are either shared between both types of expressions, or derived from the RT.

I’ve argued previously why RO produces referentially transparent results.

If getJSON simply emitted a value after a delay, producing no side effects, does that suddenly make that function declarative? Why would the declarative-ness vs imperative-ness of a function depend on the implementation details of not even the function it depends on, but the underlying stream the dependent function produced?

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.