dedupe specification
This is the engineering specification for the MotionObservable
operator: dedupe
.
Overview
dedupe
emits values from upstream as long as they’re different from the previously-emitted value.
Example usage
stream.dedupe()
upstream | downstream
20 | 20
20 |
80 | 80
20 | 20
MVP
Expose a dedupe operator API
class MotionObservable<T> {
public func dedupe(areEqual?: EqualityCheck = deepEquals) -> MotionObservable<T>
Create local storage for the operator
Store the last-emitted value and whether or not an emission has occurred.
class MotionObservable<T> {
func dedupe(areEqual?: EqualityCheck = deepEquals) -> MotionObservable<T> {
var emitted = false
var lastValue: T?
Emit and store the new value
Use _filter
to implement the operator.
Emit upstream values if we haven’t emitted a value before or the new value does not match the
previously-emitted value. Store the newly-received value.
class MotionObservable<T> {
func dedupe(areEqual?: EqualityCheck = deepEquals) -> MotionObservable<T> {
...
return _filter { value in
if emitted && areEqual(lastValue, value) {
return false
}
lastValue = value
emitted = true
return true
}
}
Check for deep equality by default
There are multiple ways to measure equality: referential (e.g. two variables reference the same object), shallow (e.g. the keys and values in two objects are all equivalent) and deep (same as shallow, but recursive if one of the values is an object). The ==
operator in many languages uses referential equality.
An implementation may provide authors with the ability to choose how to compare values. If supported, the equality check should default to deep equals.