ReactiveCocoa/ReactiveCocoa — pull request #810 by jspahrsummers (2013-09-22 08:26:50+00:00)
Title: [WIP] 99% cold signals

**:warning: NOT READY TO MERGE :warning:**

**TLDR:** Removing most hot signals, and focusing much more heavily on the semantics of cold signals, could vastly simplify RAC (especially for newcomers). Is it worth it?

----

After [a Twitter thread](https://twitter.com/joshaber/status/379702493955260416) between @joshaber and @andymatuschak, I watched Rich Hickey's [Simple Made Easy](http://www.infoq.com/presentations/Simple-Made-Easy) talk. The biggest takeaway from this talk is the distinction emphasized between _easy_ and _simple_ (hopefully paraphrased correctly):

* Something **easy** is subjectively familiar, or within one's current understanding. It's quick to pick up because it doesn't require one to learn a new paradigm.
* Something **simple** does not [complect](http://en.wiktionary.org/wiki/complect) (conflate, confuse) different concerns — it's consistent and reduced to its most basic elements. Simplicity is an objective trait.

By these definitions, ReactiveCocoa is currently **neither easy nor simple**. It's probably impossible for it to be easy for most people, but it's unfortunately not simple either. Newcomers and experienced RAC users alike are often surprised by the framework's behavior, and confused about which of N different facilities to use to solve a problem.

There are more than a few problematic places I could point to, but I believe that the single biggest source of complexity is the coexistence of cold and hot signals:

* A **cold signal** is lazy, only doing work and sending events when a subscriber attaches. It also performs that work, _including any side effects_, once per subscription. Although this has downsides, it means that disposing a subscription will cancel any associated work, potentially saving computing resources.
* A **hot signal** is always active, and all subscribers to a hot signal receive the exact same events. Since any side effects are independent of the signal lifetime, they cannot be canceled by disposing of a subscription.

Exacerbating the problem, there are also **warm signals**, including replay subjects (which are always active as subjects, but also perform unique work upon subscription) and autoconnected signals (which present any signal as being hot, but dispose of the underlying cold subscription when all hot subscribers detach).

Now, these all exist because they all have legitimate uses, so it'd be silly to _completely_ eradicate any of the above from the framework, but I'm interested in focusing most of the framework behind _one_ kind for simplicity.

As implied by the PR title, I think we should focus our semantics on cold signals, because:

1. Laziness and cancelability are useful and desirable properties, because they minimize unnecessary work.
1. Hot (and warm) signals are often based on cold signals in practice.
1. Subjects are the "mutable variables" of Rx/RAC, and we currently [recommend against their use](https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/Documentation/DesignGuidelines.md#avoid-using-subjects-when-possible).
1. Most uses of subjects can be replaced with `+[RACSignal createSignal:]`.
1. Most of the _other_ patterns that subjects are useful for can now be accomplished with higher-level abstractions, like `-rac_signalForSelector:` for observing delegate callbacks.

A world without hot signals creates two important expectations — namely, that **signals consistently represent deferred work**, and **subscriptions are consistently side-effecting**.

I don't mean that signals would _always_ have side effects, but instead that code should be written _as if_ they always do. `RACSignal` objects do not need to be traced back to their instantiation point in order for one to determine how to use them.

How exactly we'd get to this point is still a bit nebulous, because I want to have the discussion first, but the high-level changes might include:

1. Removing subjects (especially replay subjects)
1. Paring down the multicasting API so that it's only useful in very narrow circumstances — basically, for sharing side effects between multiple subscriptions in the same scope
1. Making `RACCommand` lazier

Some hot signals would remain, simply because they make certain patterns much easier (e.g., two-way bindings with `RACChannel`), but maybe we could hide them more deeply within the framework, or figure out ways to discourage their use in favor of cold alternatives.

Thoughts?

@jonsterling @paulcbetts @mattpodwysocki