ReactiveCocoa/ReactiveCocoa — pull request #756 by brow (2013-08-19 19:28:32+00:00)
Title: oneOf: operator to merge differently typed signals

Suppose I want to derive a signal of arrays from a signal of insertions (`addedObjects`) and a signal of deletions (`removedObjectIndexes`), which are applied to an empty array in the order they are sent.

This seems like it should be a merge followed by a scan. But while scanning through the merged signal of insertions and deletions, I need to distinguish between the two kinds of values, not least because one is `NSNumber` and the other can be any `NSObject` type.

Here's a broken approach:

[[[RACSignal
merge:@[addedObjects, removedObjectIndexes]]
scanWithStart:@[]
reduce:^(NSArray *running, id next) {
if ([next isKindOfClass:[NSNumber class]])
return [running arrayByRemovingObjectAtIndex:[next unsignedIntegerValue]];
else
return [running arrayByAddingObject:next];
}]
startWith:@[]];

Here's what I'd like to be able to do instead:

[[[RACSignal
oneOf:@[addedObjects, removedObjectIndexes]]
scanWithStart:@[]
reduce:^(NSArray *running, RACTuple *next) {
RACTupleUnpack(id addedObject, NSNumber *removedObjectIndex) = next;
if (removedObjectIndex)
return [running arrayByRemovingObjectAtIndex:
removedObjectIndex.unsignedIntegerValue];
else if (addedObject)
return [running arrayByAddingObject:addedObject];
else
return running;
}]
startWith:@[]];

So, if `merge:` is `[Signal a] -> Signal a`, then `oneOf:` is like `Signal a -> Signal b -> Signal (Either a b)`, except that it accepts any number of input signals and uses `RACTuple` as a make-believe `Either`.

Is there a better solution to this case? Is `oneOf:` really needed?