std/io

Standard input and the streams every process is started with - readLine for the short form, Source and Sink for the rest.

The generated reference of std/io has every public construct with its signature, its doc comment and its examples.

std/io is the three streams every process is started with. They are ordinary Source and Sink values (see std/stream), so everything that reads a file reads standard input and everything that writes a file writes to the screen. print/printError of std/console 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.

Import#

use readLine, standardInput, standardOutput, standardError from "std/io"
use readLine from "std/io"

match readLine() {
  Ok(Some(line)) => print line
  Ok(None) => print "no input"
  Fail(problem) => print problem
}

Declarations#

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 bytes that cannot be text are a property of the data and not a mistake of the program - a Result, never a panic, as for a file. A loop over the lines is while const Some(line) = readLine()? { ... } inside a function that answers a Result.

standardInput, standardOutput, standardError#

fn standardInput(): Source<Bytes, IoError>
fn standardOutput(): Sink<Bytes, IoError>
fn standardError(): Sink<Bytes, IoError>

Standard input as a stream of byte chunks. standardOutput() is not buffered - every add goes out immediately - so standardOutput().buffered(capacity: 4096) is the form for a program that writes a lot of small pieces, and it says where the flush is. standardError() stays unbuffered for the reason it always is: a diagnostic that is lost is worse than a slow one. What a sink of standard output takes and what print writes go through one lock, so the two appear in the order they were written - and neither waits in a buffer: print hands each line to the operating system before it returns, into a pipe or a file as into a terminal (std/console). A read of standard input and a write to a console or a pipe run on a thread of the blocking pool - no platform lets a poller wait for a console - so the worker that awaits it goes on meanwhile.

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. Reading from a Source needs .await() on every next() (see std/task); readLine() does not touch Task at all. Both read the one standard input, so a program uses one of them.

use lines from "std/io"
use IoError from "std/fs"

fn countLines(): Task<Result<Int, IoError>> {
  var count = 0
  var input = lines()
  while const Some(_) = input.next().await()? {
    count = count + 1
  }
  count
}
Esc