A stream contains a series of data of some type (often characters). An input stream can return a series of data using the in_stream protocol. An output stream can accept a series of data using the out_stream protocol.
Unlike sequence operations, stream operations side-effect the stream. The data can only be read or written once, unless the stream supports some kind of "rewind" operation.
There are several classes that implement one or both stream protocols and they advertise that fact by inheriting from in_stream or out_stream as a superclass.
in_stream and out_stream are generic classes with a generic formal parameter that specifies the type of the data in the stream.
The input stream protocol could have been defined by:
abstract: defclass in_stream[member_type type] require more?(s in_stream) => boolean ; false if at end of stream require[type] next(s in_stream[type]) => type | false ; next datum, or false at end require[type] next!(s in_stream[type]) => type | false ; next, also advance past that datum require close(s in_stream) ; release resources, if any
Repeated calls to next without calling next! will return the same result.
The output stream protocol could have been defined by:
abstract: defclass out_stream[member_type type] require[type] push!(s out_stream[type], x type) ; output x to stream require[type] append!(s out_stream[type], ; output x... to stream x sequence[type]) require close(s out_stream) ; release resources, if any
The in_stream pseudo-constructor takes a sequence and produces a stream that returns the members of the sequence. This is especially useful when the argument is a string. It could have been defined by
def[T] in_stream(seq sequence[T]) sequence_in_stream[T](seq) defclass sequence_in_stream[T type](seq sequence[T]) in_stream[T] sequence = seq position := iterate(seq) def more?(stream sequence_in_stream) more?(stream.sequence, stream.position) def next(stream sequence_in_stream) more?(stream.sequence, stream.position) and next(stream.sequence, stream.position) def next!(stream sequence_in_stream) if more?(stream.sequence, stream.position) def result = next(stream.sequence, stream.position) stream.position := iterate(stream.sequence, stream.position) result def close(stream sequence_in_stream) stream.position := false
The out_stream pseudo-constructor takes a type and produces a stream that accepts output. When closed it returns the data that were output to the stream as an instance of the specified type, typically string or list. If the type is not string it must be a constructor that accepts the members as multiple actual parameters. It could have been defined by
def out_stream(result_type type) sequence_out_stream(result_type) defclass sequence_out_stream(result_type type) out_stream[member_type(result_type)] result_type = result_type buffer = stack[member_type(result_type)]() def push!(stream sequence_out_stream, item) push!(stream.buffer, item) def append!(stream sequence_out_stream, items) append!(stream.buffer, items) def close(stream sequence_out_stream) def result = if stream.result_type = string then string(stream.buffer) else stream.result_type(stream.buffer...) ;; release resources stream.buffer._contents := list![member_type(result_type)]() result
See File IO for related classes for reading and writing files.
See Token Streams for a related class used by the parser.
Previous page Table of Contents Next page