Standard ML Basis Library defines a three-layer input and output facility for Standard ML. These modules provide a rudimentary, platform-independent text I/O facility that we summarize briefly here. The reader is referred to the IO section of the Standard ML Basis Library for more details. There is no standard library for graphical user interfaces; each implementation provides its own package. See your vendor's documentation for details.
The text I/O primitives are based on the notions of an input stream and an output
stream, which are values of type instream
and outstream
,
respectively. An input stream is an unbounded sequence of characters arising from
some source. The source could be a disk file, an interactive user, or another
program (to name a few choices). Any source of characters can be attached to an
input stream. An input stream may be thought of as a buffer containing zero or more
characters that have already been read from the source, together with a means of
requesting more input from the source should the program require it. Similarly, an
output stream is an unbounded sequence of characters leading to some sink. The sink
could be a disk file, an interactive user, or another program (to name a few
choices). Any sink for characters can be attached to an output stream. An
output stream may be thought of as a buffer containing zero or more characters that have
been produced by the program but have yet to be flushed to the sink.
Each program comes with one input stream and one output stream, called stdIn
and stdOut
, respectively. These are ordinarily connected to the user's
keyboard and screen, and are used for performing simple text I/O in a program. The
output stream stdErr
is also pre-defined, and is used for error reporting.
It is ordinarily connected to the user's screen.
Textual input and output are performed on streams using a variety of primitives.
The simplest are inputLine
and print
. To read a line of
input from a stream, use the function inputLine
of type instream ->
string
. It reads a line of input from the given stream and yields that line
as a string whose last character is the line terminator. If the source is exhausted,
return the empty string. To write a line to stdOut
, use the function print
of type string -> unit
. To write to a specific stream, use the
function output
of type outstream * string -> unit
, which
writes the given string to the specified output stream. For interactive applications
it is often important to ensure that the output stream is flushed to the sink (e.g.,
so that it is displayed on the screen). This is achieved by calling flushOut
of type outstream -> unit
, which ensures that the output stream is flushed
to the sink. The print function is a composition of output
(to stdOut
)
and flushOut
.
A new input stream may be created by calling the function openIn
of type string
-> instream
. When applied to a string, the system attempts to open a file
with that name (according to operating system-specific naming conventions) and attaches it
as a source to a new input stream. Similarly, a new output stream may be created by
calling the function openOut
of type string -> outstream
.
When applied to a string, the system attempts to create a file with that name
(according to operating system-specific naming conventions) and attaches it as a sink for
a new output stream. An input stream may be closed using the function closeIn
of type instream -> unit
. A closed input stream behaves as if there
is no further input available; request for input from a closed input stream yield the
empty string. An output stream may be closed using closeOut
of type outstream
-> unit
. A closed output stream is unavailable for further output; an
attempt to write to a closed output stream raises the exception TextIO.IO
.
The function input
of type instream -> string
is a
blocking read operation that returns a string consisting of the characters currently
available from the source. If none are currently available, but the end of source
has not been reached, then the operation blocks until at least one character is available
from the source. If the source is exhausted or the input stream is closed, input
returns the null string. To test whether an input
operation would
block, use the function canInput
of type instream * int -> int
option. Given a stream s and a bound n, canInput
determines whether or not a call to input
would immediately yield up to n
characters. If the input
operation would block, canInput
yields NONE
; otherwise it yields SOME
k, with 0<=k<=n
being the number of characters immediately available on the input stream. If canInput
yields SOME 0
, the stream is either closed or exhausted. The function endOfStream
of type instream -> bool
tests whether the input stream is currently at
the end (no further input is available from the source). This condition is
transitive since, for example, another process might append data to an open file in
between calls to endOfStream
.
The function output
of type outstream * string -> unit
writes a string to an output stream. It may block until the sink is able to accept
the entire string. The function flushOut
of type outstream ->
unit
forces any pending output to the sink, blocking until the sink accepts the
remaining buffered output.
This collection of primitive I/O operations is sufficient for performing rudimentary textual I/O. For further information on textual I/O, and support for binary I/O and Posix I/O primitives, see the Standard ML Basis Library.