-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
Short description of the issue:
There currently exists an overload of distinctUntilChanged on ObservableType which takes no arguments and is constrained to where E: Equatable. It simply implements the comparer by delegating to == on the Equatable element. This is useful since it lets us do:
Observable<String>().distinctUntilChanged()rather than:
Observable<String>().distinctUntilChanged { $0 == $1 }Unfortunately, we're not afforded the same syntactic brevity when dealing with tuples whose elements all conform to Equatable.
Expected outcome:
Ideally, we'd be able to write something like:
Observable
.combineLatest(
Observable<String>(),
Observable<Int>()
)
.distinctUntilChanged()What actually happens:
Since tuples cannot conform to protocols, we're faced with a compiler error:
error: referencing instance method 'distinctUntilChanged()' on 'ObservableType' requires that '(String, Int)' conform to 'Equatable'
To get around this, we can apply distinctUntilChanged() onto both of the inner observables instead:
Observable
.combineLatest(
Observable<String>().distinctUntilChanged(),
Observable<Int>().distinctUntilChanged()
)Or alternatively, we can ad-hoc implement our own comparer:
Observable
.combineLatest(
Observable<String>(),
Observable<Int>()
)
.distinctUntilChanged { $0 == $1 }The last example works not because the tuple conforms to Equatable, but because the standard library provides us with implementations of == and != for tuples of up to arity 6 (see Tuple Comparison). It's also the only solution for observables that begin as tuples, rather than the result of combining multiple observables.
Proposed solution:
It's possible to implement an overload (or more, depending on arity) of distinctUntilChanged for tuples that similarly takes no arguments, and implements comparer using the == overloads for tuples.
For example, for 2-element tuples:
extension ObservableType {
public func distinctUntilChanged<A: Equatable, B: Equatable>() -> Observable<(A, B)> where E == (A, B) {
return self.distinctUntilChanged { $0 == $1 }
}
}Resulting in the code seen in "Expected outcome" being valid.
I'd be more than happy to make a pull request if the proposal is considered worthwhile. Thanks!