Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Commit

Permalink
Merge pull request ReactiveCocoa#1638 from ReactiveCocoa/combining-co…
Browse files Browse the repository at this point in the history
…nveniences

Add combineLatest() and zip() over multiple signals
  • Loading branch information
joshaber committed Dec 22, 2014
2 parents 67f98f7 + 2daee11 commit e94a432
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 0 deletions.
6 changes: 6 additions & 0 deletions ReactiveCocoa.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
270DE4451A1EAB4600151031 /* ObservablePropertySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277F6A951A1EAA10003E0EC9 /* ObservablePropertySpec.swift */; };
270DE4461A1EACA200151031 /* ObservablePropertySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277F6A951A1EAA10003E0EC9 /* ObservablePropertySpec.swift */; };
D00004091A46864E000E7D41 /* TupleExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00004081A46864E000E7D41 /* TupleExtensions.swift */; };
D000040A1A46864E000E7D41 /* TupleExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00004081A46864E000E7D41 /* TupleExtensions.swift */; };
D01792021A34D79100A7B229 /* ColdSignalSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01792011A34D79100A7B229 /* ColdSignalSpec.swift */; };
D01792031A34D79100A7B229 /* ColdSignalSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01792011A34D79100A7B229 /* ColdSignalSpec.swift */; };
D01B7B6219EDD8FE00D26E01 /* Nimble.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D05E662419EDD82000904ACA /* Nimble.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -474,6 +476,7 @@

/* Begin PBXFileReference section */
277F6A951A1EAA10003E0EC9 /* ObservablePropertySpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObservablePropertySpec.swift; sourceTree = "<group>"; };
D00004081A46864E000E7D41 /* TupleExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TupleExtensions.swift; sourceTree = "<group>"; };
D01792011A34D79100A7B229 /* ColdSignalSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColdSignalSpec.swift; sourceTree = "<group>"; };
D037642A19EDA41200A782A9 /* NSArray+RACSequenceAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+RACSequenceAdditions.h"; sourceTree = "<group>"; };
D037642B19EDA41200A782A9 /* NSArray+RACSequenceAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+RACSequenceAdditions.m"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1116,6 +1119,7 @@
D0C312BB19EF2A5800984962 /* Atomic.swift */,
D0C312BC19EF2A5800984962 /* Bag.swift */,
D0C312C519EF2A5800984962 /* OptionalExtensions.swift */,
D00004081A46864E000E7D41 /* TupleExtensions.swift */,
);
name = "Internal Utilities";
sourceTree = "<group>";
Expand Down Expand Up @@ -1588,6 +1592,7 @@
D03765C819EDA41200A782A9 /* RACScopedDisposable.m in Sources */,
D03764FE19EDA41200A782A9 /* NSEnumerator+RACSequenceAdditions.m in Sources */,
D03764EA19EDA41200A782A9 /* NSArray+RACSequenceAdditions.m in Sources */,
D00004091A46864E000E7D41 /* TupleExtensions.swift in Sources */,
D0C312E119EF2A5800984962 /* OptionalExtensions.swift in Sources */,
D03765C019EDA41200A782A9 /* RACScheduler.m in Sources */,
D0C312D519EF2A5800984962 /* Errors.swift in Sources */,
Expand Down Expand Up @@ -1792,6 +1797,7 @@
D03B4A3E19F4C39A009E02AC /* FoundationExtensions.swift in Sources */,
D037657519EDA41200A782A9 /* RACDynamicSequence.m in Sources */,
D037657119EDA41200A782A9 /* RACDisposable.m in Sources */,
D000040A1A46864E000E7D41 /* TupleExtensions.swift in Sources */,
D03765DB19EDA41200A782A9 /* RACSignalProvider.d in Sources */,
D037653319EDA41200A782A9 /* NSSet+RACSequenceAdditions.m in Sources */,
D037665319EDA41200A782A9 /* UISwitch+RACSignalSupport.m in Sources */,
Expand Down
108 changes: 108 additions & 0 deletions ReactiveCocoa/Swift/ColdSignal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,114 @@ extension ColdSignal {
}
}

/// An overloaded function that combines the values of up to 10 signals, in the
/// manner described by ColdSignal.combineLatestWith().
public func combineLatest<A, B>(a: ColdSignal<A>, b: ColdSignal<B>) -> ColdSignal<(A, B)> {
return a.combineLatestWith(b)
}

public func combineLatest<A, B, C>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>) -> ColdSignal<(A, B, C)> {
return combineLatest(a, b)
.combineLatestWith(c)
.map(repack)
}

public func combineLatest<A, B, C, D>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>) -> ColdSignal<(A, B, C, D)> {
return combineLatest(a, b, c)
.combineLatestWith(d)
.map(repack)
}

public func combineLatest<A, B, C, D, E>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>) -> ColdSignal<(A, B, C, D, E)> {
return combineLatest(a, b, c, d)
.combineLatestWith(e)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>) -> ColdSignal<(A, B, C, D, E, F)> {
return combineLatest(a, b, c, d, e)
.combineLatestWith(f)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F, G>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>, g: ColdSignal<G>) -> ColdSignal<(A, B, C, D, E, F, G)> {
return combineLatest(a, b, c, d, e, f)
.combineLatestWith(g)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F, G, H>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>, g: ColdSignal<G>, h: ColdSignal<H>) -> ColdSignal<(A, B, C, D, E, F, G, H)> {
return combineLatest(a, b, c, d, e, f, g)
.combineLatestWith(h)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F, G, H, I>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>, g: ColdSignal<G>, h: ColdSignal<H>, i: ColdSignal<I>) -> ColdSignal<(A, B, C, D, E, F, G, H, I)> {
return combineLatest(a, b, c, d, e, f, g, h)
.combineLatestWith(i)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F, G, H, I, J>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>, g: ColdSignal<G>, h: ColdSignal<H>, i: ColdSignal<I>, j: ColdSignal<J>) -> ColdSignal<(A, B, C, D, E, F, G, H, I, J)> {
return combineLatest(a, b, c, d, e, f, g, h, i)
.combineLatestWith(j)
.map(repack)
}

/// An overloaded function that zips the values of up to 10 signals, in the
/// manner described by ColdSignal.zipWith().
public func zip<A, B>(a: ColdSignal<A>, b: ColdSignal<B>) -> ColdSignal<(A, B)> {
return a.zipWith(b)
}

public func zip<A, B, C>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>) -> ColdSignal<(A, B, C)> {
return zip(a, b)
.zipWith(c)
.map(repack)
}

public func zip<A, B, C, D>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>) -> ColdSignal<(A, B, C, D)> {
return zip(a, b, c)
.zipWith(d)
.map(repack)
}

public func zip<A, B, C, D, E>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>) -> ColdSignal<(A, B, C, D, E)> {
return zip(a, b, c, d)
.zipWith(e)
.map(repack)
}

public func zip<A, B, C, D, E, F>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>) -> ColdSignal<(A, B, C, D, E, F)> {
return zip(a, b, c, d, e)
.zipWith(f)
.map(repack)
}

public func zip<A, B, C, D, E, F, G>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>, g: ColdSignal<G>) -> ColdSignal<(A, B, C, D, E, F, G)> {
return zip(a, b, c, d, e, f)
.zipWith(g)
.map(repack)
}

public func zip<A, B, C, D, E, F, G, H>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>, g: ColdSignal<G>, h: ColdSignal<H>) -> ColdSignal<(A, B, C, D, E, F, G, H)> {
return zip(a, b, c, d, e, f, g)
.zipWith(h)
.map(repack)
}

public func zip<A, B, C, D, E, F, G, H, I>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>, g: ColdSignal<G>, h: ColdSignal<H>, i: ColdSignal<I>) -> ColdSignal<(A, B, C, D, E, F, G, H, I)> {
return zip(a, b, c, d, e, f, g, h)
.zipWith(i)
.map(repack)
}

public func zip<A, B, C, D, E, F, G, H, I, J>(a: ColdSignal<A>, b: ColdSignal<B>, c: ColdSignal<C>, d: ColdSignal<D>, e: ColdSignal<E>, f: ColdSignal<F>, g: ColdSignal<G>, h: ColdSignal<H>, i: ColdSignal<I>, j: ColdSignal<J>) -> ColdSignal<(A, B, C, D, E, F, G, H, I, J)> {
return zip(a, b, c, d, e, f, g, h, i)
.zipWith(j)
.map(repack)
}

/// Blocking methods for receiving values.
extension ColdSignal {
/// Starts the receiver, then returns the first value received.
Expand Down
108 changes: 108 additions & 0 deletions ReactiveCocoa/Swift/HotSignal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,114 @@ extension HotSignal {
}
}

/// An overloaded function that combines the values of up to 10 signals, in the
/// manner described by HotSignal.combineLatestWith().
public func combineLatest<A, B>(a: HotSignal<A>, b: HotSignal<B>) -> HotSignal<(A, B)> {
return a.combineLatestWith(b)
}

public func combineLatest<A, B, C>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>) -> HotSignal<(A, B, C)> {
return combineLatest(a, b)
.combineLatestWith(c)
.map(repack)
}

public func combineLatest<A, B, C, D>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>) -> HotSignal<(A, B, C, D)> {
return combineLatest(a, b, c)
.combineLatestWith(d)
.map(repack)
}

public func combineLatest<A, B, C, D, E>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>) -> HotSignal<(A, B, C, D, E)> {
return combineLatest(a, b, c, d)
.combineLatestWith(e)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>) -> HotSignal<(A, B, C, D, E, F)> {
return combineLatest(a, b, c, d, e)
.combineLatestWith(f)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F, G>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>, g: HotSignal<G>) -> HotSignal<(A, B, C, D, E, F, G)> {
return combineLatest(a, b, c, d, e, f)
.combineLatestWith(g)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F, G, H>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>, g: HotSignal<G>, h: HotSignal<H>) -> HotSignal<(A, B, C, D, E, F, G, H)> {
return combineLatest(a, b, c, d, e, f, g)
.combineLatestWith(h)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F, G, H, I>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>, g: HotSignal<G>, h: HotSignal<H>, i: HotSignal<I>) -> HotSignal<(A, B, C, D, E, F, G, H, I)> {
return combineLatest(a, b, c, d, e, f, g, h)
.combineLatestWith(i)
.map(repack)
}

public func combineLatest<A, B, C, D, E, F, G, H, I, J>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>, g: HotSignal<G>, h: HotSignal<H>, i: HotSignal<I>, j: HotSignal<J>) -> HotSignal<(A, B, C, D, E, F, G, H, I, J)> {
return combineLatest(a, b, c, d, e, f, g, h, i)
.combineLatestWith(j)
.map(repack)
}

/// An overloaded function that zips the values of up to 10 signals, in the
/// manner described by HotSignal.zipWith().
public func zip<A, B>(a: HotSignal<A>, b: HotSignal<B>) -> HotSignal<(A, B)> {
return a.zipWith(b)
}

public func zip<A, B, C>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>) -> HotSignal<(A, B, C)> {
return zip(a, b)
.zipWith(c)
.map(repack)
}

public func zip<A, B, C, D>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>) -> HotSignal<(A, B, C, D)> {
return zip(a, b, c)
.zipWith(d)
.map(repack)
}

public func zip<A, B, C, D, E>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>) -> HotSignal<(A, B, C, D, E)> {
return zip(a, b, c, d)
.zipWith(e)
.map(repack)
}

public func zip<A, B, C, D, E, F>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>) -> HotSignal<(A, B, C, D, E, F)> {
return zip(a, b, c, d, e)
.zipWith(f)
.map(repack)
}

public func zip<A, B, C, D, E, F, G>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>, g: HotSignal<G>) -> HotSignal<(A, B, C, D, E, F, G)> {
return zip(a, b, c, d, e, f)
.zipWith(g)
.map(repack)
}

public func zip<A, B, C, D, E, F, G, H>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>, g: HotSignal<G>, h: HotSignal<H>) -> HotSignal<(A, B, C, D, E, F, G, H)> {
return zip(a, b, c, d, e, f, g)
.zipWith(h)
.map(repack)
}

public func zip<A, B, C, D, E, F, G, H, I>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>, g: HotSignal<G>, h: HotSignal<H>, i: HotSignal<I>) -> HotSignal<(A, B, C, D, E, F, G, H, I)> {
return zip(a, b, c, d, e, f, g, h)
.zipWith(i)
.map(repack)
}

public func zip<A, B, C, D, E, F, G, H, I, J>(a: HotSignal<A>, b: HotSignal<B>, c: HotSignal<C>, d: HotSignal<D>, e: HotSignal<E>, f: HotSignal<F>, g: HotSignal<G>, h: HotSignal<H>, i: HotSignal<I>, j: HotSignal<J>) -> HotSignal<(A, B, C, D, E, F, G, H, I, J)> {
return zip(a, b, c, d, e, f, g, h, i)
.zipWith(j)
.map(repack)
}

/// Conversions from HotSignal to ColdSignal.
extension HotSignal {
/// Buffers `count` values, starting at the time of the method invocation.
Expand Down
52 changes: 52 additions & 0 deletions ReactiveCocoa/Swift/TupleExtensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// TupleExtensions.swift
// ReactiveCocoa
//
// Created by Justin Spahr-Summers on 2014-12-20.
// Copyright (c) 2014 GitHub. All rights reserved.
//

import Foundation

/// Adds a value into an N-tuple, returning an (N+1)-tuple.
///
/// Supports creating tuples up to 10 elements long.
internal func repack<A>(t: (), value: A) -> (A) {
return (value)
}

internal func repack<A, B>(t: (A), value: B) -> (A, B) {
return (t.0, value)
}

internal func repack<A, B, C>(t: (A, B), value: C) -> (A, B, C) {
return (t.0, t.1, value)
}

internal func repack<A, B, C, D>(t: (A, B, C), value: D) -> (A, B, C, D) {
return (t.0, t.1, t.2, value)
}

internal func repack<A, B, C, D, E>(t: (A, B, C, D), value: E) -> (A, B, C, D, E) {
return (t.0, t.1, t.2, t.3, value)
}

internal func repack<A, B, C, D, E, F>(t: (A, B, C, D, E), value: F) -> (A, B, C, D, E, F) {
return (t.0, t.1, t.2, t.3, t.4, value)
}

internal func repack<A, B, C, D, E, F, G>(t: (A, B, C, D, E, F), value: G) -> (A, B, C, D, E, F, G) {
return (t.0, t.1, t.2, t.3, t.4, t.5, value)
}

internal func repack<A, B, C, D, E, F, G, H>(t: (A, B, C, D, E, F, G), value: H) -> (A, B, C, D, E, F, G, H) {
return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, value)
}

internal func repack<A, B, C, D, E, F, G, H, I>(t: (A, B, C, D, E, F, G, H), value: I) -> (A, B, C, D, E, F, G, H, I) {
return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, t.7, value)
}

internal func repack<A, B, C, D, E, F, G, H, I, J>(t: (A, B, C, D, E, F, G, H, I), value: J) -> (A, B, C, D, E, F, G, H, I, J) {
return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, t.7, t.8, value)
}

0 comments on commit e94a432

Please sign in to comment.