std/io/lib
std/io/src/lib.trb
The three streams every process is started with. They are ordinary Source and Sink values (docs/design/STREAMS.md),
so everything that reads a file reads standard input, and everything that writes a file writes to the screen:
const total = lines().count().await()?
standardOutput().addLine("{total} lines").await()?
print/printError of the prelude and readLine() here stay as the short form for the common case: a program that
prints a line does not want to think about a stream.
fn readLine
fn readLine(): Result<String?, IoError>
The next line of standard input without its line break: Ok(None) at the end of the input, and an IoError for a
line whose bytes are not UTF-8.
Standard input comes from outside the program, so its bytes are a property of the data and not a promise the program
made: a line that cannot be text is a Result and never a panic (CONCEPT.md, "Error Handling").
Examples
while const Some(line) = readLine()? {
print line.toUpperCase()
}
fn standardInput
fn standardInput(): Source<Bytes, IoError>
Standard input as a stream of byte chunks, each read on a thread of the blocking pool as it arrives.
fn standardOutput
fn standardOutput(): Sink<Bytes, IoError>
Standard output as a stream of byte chunks. Not buffered: every add goes out. standardOutput().buffered(capacity: 4096) is the form a program that writes a lot of small pieces wants, and it says where the flush is.
fn standardError
fn standardError(): Sink<Bytes, IoError>
Standard error, unbuffered for the reason it is everywhere: a diagnostic that is lost is worse than a slow one.
fn lines
fn lines(): Source<String, IoError>
The lines of standard input, as a stream: the same stage File.lines uses, over the same kind of source.
Examples
const total = lines().count().await()
print total