10
Behaviors are values you poll, not events you wait for
The current time and the current temperature change continuously. It would be neither meaningful nor possible to respond every moment they change, so nobody pushes them. Instead the consumer pulls a value when it needs one, at its own rate: a display at its frame rate, a logger once a minute.
A behavior represents a time series value. A behavior may produce a different value for every moment in time. As such, they must be polled at an interval meaningful to the consumer, since the behavior itself has no inherent resolution.
A thermocouple, a sensor, a display
behavior: temperature(t), continuoussensor sampleswhat the display shows
display
—°
redrawn (remembered)
0
forgotten (never shown)
0
The sensor is slower than the display. It is sufficient to remember the last sensed temperature and redisplay it: the green line holds flat between pink dots.
Scroll position: a discrete signal, sampled as a behavior
line 1 — scroll me
line 2
line 3
line 4
line 5
line 6
line 7
line 8 — scroll me
line 9
line 10
line 11
line 12
line 13
line 14
line 15 — scroll me
line 16
line 17
line 18
line 19
line 20
line 21
line 22 — scroll me
line 23
line 24
line 25
line 26
line 27
line 28
line 29 — scroll me
line 30
line 31
line 32
line 33
line 34
line 35
line 36 — scroll me
line 37
line 38
line 39
line 40
line 41
line 42
line 43 — scroll me
line 44
line 45
line 46
line 47
line 48
line 49
line 50 — scroll me
line 51
line 52
line 53
line 54
line 55
line 56
line 57 — scroll me
line 58
line 59
line 60
scroll events (discrete, pushed)inferred position(t), polled every frame
Scroll quickly and the pink dots bunch up or leave gaps; the blue curve stays smooth. The display polls the behavior at its own rate, the frame rate, so it never cares how often events arrived.
The interface
// A behavior has no setter: it produces a value for any time, on demand.
var temperature = new Behavior(function (time) {
return readThermocouple(time);
});
// The consumer decides when to sample. Here: once per animation frame.
function frame(now) {
display.textContent = temperature.next(now).value;
requestAnimationFrame(frame);
}
// Operators lift into behaviors: polling the result polls the operands.
var fahrenheit = Behavior.lift(function (c) { return c * 9 / 5 + 32; })(temperature);Push vs poll, from the essay
| Interface | Side | Flow |
|---|---|---|
| Signal Observable | Get | Push |
| Signal Generator | Set | Push |
| Signal | Value | Push |
| Behavior Iterator | Get | Poll |
| Behavior Generator | Set | Poll |
| Behavior | Value | Poll |
Discrete values should be pushed; continuous values should be pulled or polled. Even behaviors come in variations: probes, gauges, counters, flow gauges, accumulators and rotating counters.
- why it mattersThe behavior has no resolution of its own. Move the sliders: the same thermocouple yields a jagged or a smooth picture depending only on how often the consumer chooses to look.
- why it mattersRate mismatches are resolved by meaning, not by pressure. Slower sensor: remember the last value. Faster sensor: forget the stale ones. Neither side ever waits for the other.
- why it mattersSignals and behaviors convert into each other: discrete scroll events become a continuous function you can sample every frame, and polling a signal's
next()treats it as a behavior.