Streams
Streams
Two arrows turn a single packet into a batch of packets, and back again. They are exact inverses:
=>splits — one array packet becomes one delivery per element.>=collects — a stream of packets becomes one array when the batch closes.
=> — the cyclic feed
["a", "b", "c"] => in Echo(stream/echo)
The => arrow marks the target port as cyclic. When an array arrives, the runtime splits it and delivers one element at a time: Echo runs three times, receiving "a", then "b", then "c".
The split is unconditional — a flat array feeds each element to a scalar port separately, while an array-of-arrays feeds an array port one sub-array per delivery. A non-array value fails loudly rather than being silently dropped.
=> is the loop/recurrence feed: feeding a node's output back through => makes it process a stream in bounded steps instead of all at once.
>= — the collect
Echo out >= in Collect(console/log)
The >= arrow marks the source port as collecting. Packets that cross the link are buffered, and when the batch closes the whole stream is flushed as one array packet. Collect receives ["a", "b", "c"] in a single run.
Collecting is the inverse of splitting: whatever was deconstructed by => can be reconstructed by >=, without knowing how many items there were.
Batches and end-of-stream
A batch is a set of deliveries that the runtime knows has a beginning and an end. The end of a batch is called end-of-stream (EOS), and it is what lets a collector know when to flush.
The rule to remember:
A finite stream requires a batch boundary. A cyclic feed (
=>) opens a batch, delivers each element, and closes it. A plain (non-cyclic) IIP writes one packet and never closes a batch — so a>=collector fed by a plain link never flushes until the run ends.
That is why the three arrows work together:
["a", "b", "c"] => in Echo(stream/echo)
Echo out >= in Collect(console/log)
The => is what makes the stream finite: it closes the batch, the close relays through Echo, and the collector flushes on it.
A >= wire fed by a plain -> source still materializes — the batch closes when the run completes, so a single packet collects to a list of one:
'just one' -> in Dummy(utils/dummy)
Dummy out >= in Collect(console/log) # Collect receives ["just one"] when the run ends
What streams make possible
- Streaming nodes consume the per-packet feed directly. A
streaming: truenode with a barefnruns once per packet — the runtime owns the loop. See the streaming reference. - Materializing a stream into a plain node is exactly what
>=is for: it is a legitimate stream terminator that hands a buffering consumer the whole list at once.
The =>/>= pair and the batch/EOS relay are implemented as port behaviors; the details of the mechanism are in the runtime.