Channels¶
An endpoint of bytes needs a format to make its bytes documents. A
channel holds values instead. Channel<T>(name) is an endpoint of values
of type T, held in memory for one evaluation. It keeps the values' type, so
it takes no format. target writes one value to it, sink writes each value
of a sequence, and source gives what it holds now:
c = Channel<Int>("nums")
1 | target(c)
[2, 3] | sink(c)
source(c)
[1, 2, 3]
Values are read in the order they were written. Reading does not consume: two reads give the same values.
c = Channel<Int>("n")
[1] | sink(c)
a = source(c)
b = source(c)
[size(a), size(b)]
[1, 1]
tap(c) gives only what is written after it, as a stream:
c = Channel<Int>("n")
[1] | sink(c)
t = tap(c)
[2] | sink(c)
t | take(5)
[2]
The element type is checked¶
A channel's T is checked as any other type is, and a format beside a
channel is a type error, since a channel holds values rather than bytes:
c = Channel<Int>("n")
"x" | target(c)
check error[type-mismatch]: Channel<Int> holds Int, not String
--> <expression>:2:7
|
2 | "x" | target(c)
| ^^^^^^^^^
c = Channel<Int>("n")
source(c, Json)
check error[type-mismatch]: a channel holds values, not bytes, so it takes no format
--> <expression>:2:8
|
2 | source(c, Json)
| ^
One name, one channel¶
A channel lives for its execution scope: a program run, or one cell of a document. Within a scope one name is one channel, and constructing the same name with another element type is an evaluation failure naming both:
a = Channel<Int>("n")
b = Channel<String>("n")
1
execute failure[invalid-argument]: the channel "n" holds Int, so it is not also a Channel<String>
--> <expression>:2:5
|
2 | b = Channel<String>("n")
| ^^^^^^^^^^^^^^^^^^^^
A cell of a document being rendered may write a channel, because a channel
stays inside the evaluation (effects and what a host allows). A
channel of LogEvent values is how a program keeps its own
logs as values.