Computed Values

Step 4: Computed Values

Real reactivity shines with derived state: a value defined as a function of another, that updates itself whenever its source changes. A Computed subscribes to its source, recomputes on every change, and, like an Observable, only notifies its own subscribers when its result changes.

  • _on_source_change(source_value): recompute self.fn(source_value); if the result differs from the current computed value, store it and notify
Hints
Starter code
class Subject:
    def __init__(self):
        self._observers = []

    def subscribe(self, observer):
        self._observers.append(observer)
        def unsubscribe():
            if observer in self._observers:
                self._observers.remove(observer)
        return unsubscribe

    def notify(self, *args):
        for observer in self._observers:
            observer(*args)


class Observable:
    def __init__(self, value=None):
        self._value = value
        self._subject = Subject()

    def get(self):
        return self._value

    def subscribe(self, observer):
        return self._subject.subscribe(observer)

    def set(self, value):
        if value == self._value:
            return
        self._value = value
        self._subject.notify(value)


class Computed:
    def __init__(self, source, fn):
        self.fn = fn
        self._value = fn(source.get())
        self._subject = Subject()
        source.subscribe(self._on_source_change)

    def get(self):
        return self._value

    def subscribe(self, observer):
        return self._subject.subscribe(observer)

    def _on_source_change(self, source_value):
        """Recompute from the source; notify only if the computed value changed."""
        # TODO: feed source_value through self.fn to get the fresh result, then weigh
        #   it against the computed value currently in self._value: identical means
        #   stay silent. Otherwise store the fresh result and have self._subject
        #   notify this Computed's own observers with it.
        pass
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.