By your definition, also this piece of code is declarative because it isn’t describing the how.
By your definition, also this piece of code is declarative because it isn’t describing the how.
Luca Matteis
1

Promises represent a calculation in progress, rather than one to occur later, which muddies the discussion a bit, but I would suggest that’s still declarative. If the code was rewritten using something like data.task, or a Future, it would be pretty clearly declarative.

Focusing on streams though: Note that the call to getJSON doesn’t trigger a side-effect, it just returns a stream; observing the stream it was triggers the side effect. If I call getJSON outside of the context of the flatMap, I get back a stream. The HTTP request itself has not yet been triggered, and won’t be triggered, until the stream itself gets observed. We’ve merely declared that at this point, we want the results of an HTTP request merged into the main stream.

In a pure functional language, the runtime would enforce that, should you call getJSON with the same parameters, you’d get back the same instance, which would make a call to getJSON referentially transparent. Two streams that do the same things could be considered “equal” in JavaScript; otherwise, even a Cycle.js stream wouldn’t be “pure” because the two streams aren’t ===.

Which means that the Epic function provided to redux-observable is pure, referentially transparent, and does not produce side effects, because streams don’t produce side effects until they’re observed, and the stream returned from the Epic is observed at the edges of the system. It’s not merely that we wrap things in functions; it’s that we wrap them in objects that represent the results of those side effects without being the side effect.

Like what you read? Give James DiGioia a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.