From 52077a4609ca3940de09bfbffdef073f9055813f Mon Sep 17 00:00:00 2001 From: Daniel Haight Date: Fri, 31 May 2019 17:13:29 +0100 Subject: [PATCH] Add combine operator and tests --- Receiver/Sources/Receiver+Operators.swift | 57 +++++++++++++++++++++ ReceiverTests/ReceiverTests+Operators.swift | 22 ++++++++ 2 files changed, 79 insertions(+) diff --git a/Receiver/Sources/Receiver+Operators.swift b/Receiver/Sources/Receiver+Operators.swift index 326bc36..dfc2cc1 100644 --- a/Receiver/Sources/Receiver+Operators.swift +++ b/Receiver/Sources/Receiver+Operators.swift @@ -288,3 +288,60 @@ extension Receiver where Wave: OptionalProtocol { return receiver } } + +/// Combines a receiver of `A` and a reveiver of `B` to produce a receiver of (A,B) +/// ``` +/// let (intTransmitter, intReceiver) = Receiver.make() +/// let (stringTransmitter, stringReceiver) = Receiver.make() +/// +/// let intAndStringReceiver = combine(intReceiver,stringReceiver) +/// } +/// +/// intAndStringReceiver.listen { value in +/// /// `value` == (1,"1") +/// /// `value` == (2,"1") +/// /// `value` == (2,"2") +/// } +/// /// Value is not sent yet since we do not have a value from stringReceiver +/// intTransmitter.broadcast(1) +/// /// Value is sent to the listener now as (1,"1") +/// stringTransmitter.broadcast("1") +/// /// Value is sent to the listener now as (2,"2") +/// intTransmitter.broadcast(2) +/// /// Value is sent to the listener now as (2,"2") +/// stringTransmitter.broadcast("2") +/// ``` +/// - parameters: +/// - ra: A receiver of type Receiver +/// - rb: A receiver of type Receiver +/// +/// - returns: A `receiver` that produces values of <(A,B)> for every value emitted from either +public func combine(_ ra: Receiver, _ rb: Receiver) -> Receiver<(A,B)> { + let (transmitter, receiver) = Receiver<(A?,B?)>.make() + let ab = Atomic<(A?,B?)>( (nil,nil) ) + + ra.listen { a in + ab.apply { + $0.0 = a + transmitter.broadcast($0) + } + } + + rb.listen { b in + ab.apply { + $0.1 = b + transmitter.broadcast($0) + } + } + + let newReceiver = receiver.map { (ab) -> (A,B)? in + if let next = ab as? (A,B) { + return next + } else { + return nil + } + }.skipNil() + + return newReceiver + +} diff --git a/ReceiverTests/ReceiverTests+Operators.swift b/ReceiverTests/ReceiverTests+Operators.swift index 1909eb3..4d3daa3 100644 --- a/ReceiverTests/ReceiverTests+Operators.swift +++ b/ReceiverTests/ReceiverTests+Operators.swift @@ -179,4 +179,26 @@ class ReceiverTests_Operators: XCTestCase { XCTAssertTrue(called == 3) } + + func test_combine() { + let (intTransmitter, intReceiver) = Receiver.make() + let (stringTransmitter, stringReceiver) = Receiver.make() + let newReceiver = combine(intReceiver, stringReceiver) + let expectedValues = [(1,"1"),(2,"1"),(2,"2")] + var values = [(Int,String)]() + + newReceiver.listen { wave in + values.append(wave) + } + + intTransmitter.broadcast(1) + stringTransmitter.broadcast("1") + intTransmitter.broadcast(2) + stringTransmitter.broadcast("2") + + XCTAssertEqual(values.map{$0.0}, expectedValues.map{$0.0}) + XCTAssertEqual(values.map{$0.1}, expectedValues.map{$0.1}) + + } + }