Material Motion Exploring solutions that will empower creators with the tools needed to describe and implement rich, interactive motion on any platform. Edit this page · History
$._filter dedupe slop · visualize
Status Interface level Implementation level Library
Stable as of February 21, 2017 L2: Interaction creator L3: Stream creator material-motion
Android View
JavaScript View View
iOS (Swift) View View
upstream (T: Equatable)
(T: Equatable) downstream

dedupe specification

This is the engineering specification for the MotionObservable operator: dedupe.


dedupe emits values from upstream as long as they’re different from the previously-emitted value.

Example usage


upstream  |  downstream
20        |  20
20        |
80        |  80
20        |  20


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.