Skip to content

Commit

Permalink
Additional overloads for some methods
Browse files Browse the repository at this point in the history
  • Loading branch information
srdanrasic committed Aug 28, 2016
1 parent 35895bc commit a646415
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 19 deletions.
3 changes: 3 additions & 0 deletions Sources/Bindable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ extension SignalProtocol {

/// Establish a one-way binding between the source and the bindable
/// and return a disposable that can cancel binding.
@discardableResult
public func bind<B: BindableProtocol>(to bindable: B) -> Disposable where B.Element == Element, B.Error == Error {
return bindable.bind(signal: filterRecursiveEvents())
}

/// Establish a one-way binding between the source and the bindable
/// and return a disposable that can cancel binding.
@discardableResult
public func bind<B: BindableProtocol>(to bindable: B) -> Disposable where B.Element: OptionalProtocol, B.Element.Wrapped == Element, B.Error == Error {
return self.map { B.Element($0) }.bind(to: bindable)
}
Expand All @@ -51,6 +53,7 @@ extension BindableProtocol where Self: SignalProtocol {

/// Establish a two-way binding between the source and the bindable
/// and return a disposable that can cancel binding.
@discardableResult
public func bidirectionalBind<B: BindableProtocol >(to bindable: B) -> Disposable where B: SignalProtocol, B.Element == Element, B.Error == Error {
let d1 = self.bind(to: bindable)
let d2 = bindable.bind(to: self)
Expand Down
121 changes: 102 additions & 19 deletions Sources/SignalProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1119,8 +1119,7 @@ public extension SignalProtocol where Element: SignalProtocol, Element.Error ==

extension SignalProtocol {

/// Propagate events only from a signal that starts emitting first.
public func amb<O: SignalProtocol>(with other: O) -> Signal<Element, Error> where O.Element == Element, O.Error == Error {
fileprivate func _amb<O: SignalProtocol>(with other: O) -> Signal<Element, Error> where O.Element == Element, O.Error == Error {
return Signal { observer in
let lock = NSRecursiveLock(name: "amb")
let disposable = (my: SerialDisposable(otherDisposable: nil), other: SerialDisposable(otherDisposable: nil))
Expand Down Expand Up @@ -1152,9 +1151,12 @@ extension SignalProtocol {
}
}

/// Emit a combination of latest elements from each signal. Starts when both signals emit at least one element,
/// and emits `.next` when either signal generates an element by calling `combine` on the two latest elements.
public func combineLatest<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
/// Propagate events only from a signal that starts emitting first.
public func amb<O: SignalProtocol>(with other: O) -> Signal<Element, Error> where O.Element == Element, O.Error == Error {
return _amb(with: other)
}

fileprivate func _combineLatest<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
return Signal { observer in
let lock = NSRecursiveLock(name: "combineLatestWith")

Expand Down Expand Up @@ -1209,20 +1211,24 @@ extension SignalProtocol {
}
}

/// Emit a combination of latest elements from each signal. Starts when both signals emit at least one element,
/// and emits `.next` when either signal generates an element by calling `combine` on the two latest elements.
public func combineLatest<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
return _combineLatest(with: other, combine: combine)
}

/// Emit a pair of latest elements from each signal. Starts when both signals emit at least one element,
/// and emits `.next` when either signal generates an element.
public func combineLatest<O: SignalProtocol>(with other: O) -> Signal<(Element, O.Element), Error> where O.Error == Error {
return combineLatest(with: other, combine: { ($0, $1) })
return _combineLatest(with: other, combine: { ($0, $1) })
}

/// Merge emissions from both the receiver and the other signal into one signal.
public func merge<O: SignalProtocol>(with other: O) -> Signal<Element, Error> where O.Element == Element, O.Error == Error {
return Signal.sequence([self.toSignal(), other.toSignal()]).merge()
}

/// Emit elements from the receiver and the other signal in pairs.
/// This differs from `combineLatest` in that the combinations are produced from elements at same positions.
public func zip<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
fileprivate func _zip<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
return Signal { observer in
let lock = NSRecursiveLock(name: "zip")

Expand Down Expand Up @@ -1279,15 +1285,19 @@ extension SignalProtocol {
}
}

/// Emit elements from the receiver and the other signal in pairs.
/// This differs from `combineLatest` in that the combinations are produced from elements at same positions.
public func zip<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
return _zip(with: other, combine: combine)
}

/// Emit elements from the receiver and the other signal in pairs.
/// This differs from `combineLatest` in that the pairs are produced from elements at same positions.
public func zip<O: SignalProtocol>(with other: O) -> Signal<(Element, O.Element), Error> where O.Error == Error {
return zip(with: other, combine: { ($0, $1) })
return _zip(with: other, combine: { ($0, $1) })
}

/// Combines the receiver and the other signal into a signal of combinations of elements whenever the
/// receiver emits an element with the latest element from the other signal.
public func with<O: SignalProtocol, U>(latestFrom other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
fileprivate func _with<O: SignalProtocol, U>(latestFrom other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
return Signal { observer in

var latest: O.Element? = nil
Expand Down Expand Up @@ -1321,10 +1331,16 @@ extension SignalProtocol {
}
}

/// Combines the receiver and the other signal into a signal of combinations of elements whenever the
/// receiver emits an element with the latest element from the other signal.
public func with<O: SignalProtocol, U>(latestFrom other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
return _with(latestFrom: other, combine: combine)
}

/// Combines the receiver and the other signal into a signal of pairs of elements whenever the
/// receiver emits an element with the latest element from the other signal.
public func with<O: SignalProtocol>(latestFrom other: O) -> Signal<(Element, O.Element), Error> where O.Error == Error {
return with(latestFrom: other, combine: { ($0, $1) })
return _with(latestFrom: other, combine: { ($0, $1) })
}
}

Expand All @@ -1339,25 +1355,92 @@ extension SignalProtocol where Error == NoError {
observer.next(element)
case .completed:
observer.completed()
case .failed: // will never happen because of NoError constraint
break
case .failed:
break // will never happen because of NoError constraint
}
}
}
}

/// Map each event into a signal and then flatten inner signals.
public func flatMapLatest<O: SignalProtocol>(transform: @escaping (Element) -> O) -> Signal<O.Element, O.Error> {
return castError().flatMapLatest(transform: transform)
return castError().map(transform).switchToLatest()
}

/// Map each event into a signal and then flatten inner signals.
public func flatMapMerge<O: SignalProtocol>(transform: @escaping (Element) -> O) -> Signal<O.Element, O.Error> {
return castError().flatMapMerge(transform: transform)
return castError().map(transform).merge()
}

/// Map each event into a signal and then flatten inner signals.
public func flatMapConcat<O: SignalProtocol>(transform: @escaping (Element) -> O) -> Signal<O.Element, O.Error> {
return castError().flatMapConcat(transform: transform)
return castError().map(transform).concat()
}

/// Transform each element by applying `transform` on it.
public func tryMap<U, E: Swift.Error>(transform: @escaping (Element) -> Result<U, E>) -> Signal<U, E> {
return Signal { observer in
return self.observe { event in
switch event {
case .next(let element):
switch transform(element) {
case .success(let value):
observer.next(value)
case .failure(let error):
observer.failed(error)
}
case .failed:
break // will never happen because of NoError constraint
case .completed:
observer.completed()
}
}
}
}

/// Propagate events only from a signal that starts emitting first.
public func amb<O: SignalProtocol>(with other: O) -> Signal<Element, O.Error> where O.Element == Element {
return castError()._amb(with: other)
}

/// Emit a combination of latest elements from each signal. Starts when both signals emit at least one element,
/// and emits `.next` when either signal generates an element by calling `combine` on the two latest elements.
public func combineLatest<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, O.Error> {
return castError()._combineLatest(with: other, combine: combine)
}

/// Emit a pair of latest elements from each signal. Starts when both signals emit at least one element,
/// and emits `.next` when either signal generates an element.
public func combineLatest<O: SignalProtocol>(with other: O) -> Signal<(Element, O.Element), O.Error> {
return castError()._combineLatest(with: other, combine: { ($0, $1) })
}

/// Merge emissions from both the receiver and the other signal into one signal.
public func merge<O: SignalProtocol>(with other: O) -> Signal<Element, O.Error> where O.Element == Element {
return Signal.sequence([toSignal().castError(), other.toSignal()]).merge()
}

/// Emit elements from the receiver and the other signal in pairs.
/// This differs from `combineLatest` in that the combinations are produced from elements at same positions.
public func zip<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, O.Error> {
return castError()._zip(with: other, combine: combine)
}

/// Emit elements from the receiver and the other signal in pairs.
/// This differs from `combineLatest` in that the pairs are produced from elements at same positions.
public func zip<O: SignalProtocol>(with other: O) -> Signal<(Element, O.Element), O.Error> {
return castError()._zip(with: other, combine: { ($0, $1) })
}

/// Combines the receiver and the other signal into a signal of combinations of elements whenever the
/// receiver emits an element with the latest element from the other signal.
public func with<O: SignalProtocol, U>(latestFrom other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, O.Error> {
return castError()._with(latestFrom: other, combine: combine)
}

/// Combines the receiver and the other signal into a signal of pairs of elements whenever the
/// receiver emits an element with the latest element from the other signal.
public func with<O: SignalProtocol>(latestFrom other: O) -> Signal<(Element, O.Element), O.Error> {
return castError()._with(latestFrom: other, combine: { ($0, $1) })
}
}

0 comments on commit a646415

Please sign in to comment.