17 Ports
A port is an object that mediates data from an input or to a destination. In the former case, the port is an input port, in the latter case, an output port. The data itself can consist of either characters or bytes. In the former case the port is a textual port and in the latter case, a binary port.
There are three textual ports open, binded by dynamic variables, one for standard input, output, and error.
Although ports are not considered immutable, none of the operations on ports described in this section constitute mutation. Ports are equal?
iff eq?
. The port type is encapsulated.
An auxiliary data type used to signal the end of file was reached is eof
. The eof type consists of a single immutable value, having an output only external representation (so that it can never be the normal result of a call to read). The eof type is encapsulated.
SOURCE NOTE: the eof type is not in the Kernel report, it is used in klisp and was taken from r7rs.
The primitive type predicate for type port.
port?
returns true iff all the objects inobjects
are of type port.
— Applicative: output-port? (output-port? . objects)
Applicative
input-port?
is a predicate that returns true unless one or more of its arguments is not an input port. Applicativeoutput-port?
is a predicate that returns true unless one or more of its arguments is not an output port.Every port must be admitted by at least one of these two predicates.
— Applicative: binary-port? (binary-port? . objects)
Applicative
textual-port?
is a predicate that returns true unless one or more of its arguments is not a textual port. Applicativebinary-port?
is a predicate that returns true unless one or more of its arguments is not a binary port.Every port must be admitted by at least one of these two predicates.
SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
— Applicative: string-port? (string-port? . objects)
— Applicative: bytevector-port? (bytevector-port? . objects)
These applictives are predicates that returns true unless one or more of its arguments is not a file, string or bytevector port, repectively.
Every port in klisp is be admitted by exactly one of these predicates.
SOURCE NOTE: this is missing from Kernel, but convenient in the face of the different port types admited by klisp.
Applicative
port-open?
returns true iffport
is still open.SOURCE NOTE: this is taken from r7rs.
— Applicative: with-output-to-file (with-output-to-file string combiner)
— Applicative: with-error-to-file (with-error-to-file string combiner)
These three applicatives open the file named in
string
for textual input or output, an invoke the binder of either the input-port, the output-port or the error-port keyed dynamic variables respectively with the opened port & the passedcombiner
(this means that the combiner is called in a fresh, empty dynamic environment). When/if the binder normally returns, the port is closed. The result of the applicativeswith-input-from-file
andwith-output-from-file
is inert.SOURCE NOTE: The first two are enumerated in the Kernel report but the text is still missing. The third applicative is from r7rs.
— Applicative: get-current-output-port (get-current-output-port)
— Applicative: get-current-error-port (get-current-error-port)
These are the accessors for the input-port, output-port, and error-port keyed dynamic variables repectively.
SOURCE NOTE: The first two are enumerated in the Kernel report but the text is still missing. The third applicative is from r7rs.
— Applicative: open-binary-input-file (open-binary-input-file string)
string
should be the name/path for an existing file.Applicative
open-input-file
creates and returns a textual input port associated with the file represented withstring
. Applicativeopen-binary-input-file
creates and returns a binary input port associated with the file represented withstring
. In either case, if the file can’t be opened (e.g. because it doesn’t exists, or there’s a permissions problem), an error is signaled.SOURCE NOTE:
open-input-file
is enumerated in the Kernel report but the text is still missing.open-binary-input-file
is from r7rs.
— Applicative: open-binary-output-file (open-binary-output-file string)
string
should be the name/path for an existing file.Applicative
open-output-file
creates and returns a textual output port associated with the file represented withstring
. Applicativeopen-binary-output-file
creates and returns a binary output port associated with the file represented withstring
. In either case, if the file can’t be opened (e.g. if there’s a permissions problem), an error is signaled.In klisp, for now, applicative
open-output-file
andopen-binary-output-file
truncate the file if it already exists, but that could change later (i.e. like in Scheme the behaviour should be considered unspecified).SOURCE NOTE:
open-output-file
is enumerated in the Kernel report but the text is still missing.open-binary-output-file
is from r7rs.
— Applicative: open-input-bytevector (open-output-bytevector bytevector)
These applicative return a fresh input port that reads characters or unsigned bytes from the passed sequence.
SOURCE NOTE: These are taken from r7rs.
Applicative
open-output-string
returns a fresh textual output port that accumulates characters. The accumulated data can be obtained via applicativeget-output-string
.SOURCE NOTE: This is taken from r7rs.
Applicative
open-output-bytevector
returns a fresh binary output port that accumulates unsigned bytes. The accumulated data can be obtained via applicativeget-output-bytevector
.SOURCE NOTE: This is taken from r7rs.
— Applicative: close-output-file (close-output-file output-port)
These applicatives close the port argument, so that no more input/output may be performed on them, and the resources can be freed. If the port was already closed these applicatives have no effect.
The result returned by applicatives
close-input-file
andclose-output-file
is inert.SOURCE NOTE: this is enumerated in the Kernel report but the text is still missing. There’s probably a name error here. These should probably be called close-input-port & close-output-port.
— Applicative: close-output-port (close-output-port output-port)
— Applicative: close-port (close-port port)
These applicatives close the port argument, so that no more input/output may be performed on them, and the resources can be freed. If the port was already closed these applicatives have no effect. If at some time klisp provided input/output ports these could be used to selectively close only one direction of the port.
The result returned by applicatives
close-input-port
,close-output-port
, andclose-port
is inert.SOURCE NOTE: this is from r7rs. The equivalent
close-input-file
andclose-output-file
are probably name errors and only retained here till the draft standard rectifies them.
port
should be a string output port.Applicative
get-output-string
returns a freshly created mutable string representing the characters accumulated inport
so far.port
can be either open or closed.SOURCE NOTE: This is taken from r7rs.
port
should be a bytevector output port.Applicative
get-output-bytevector
returns a freshly created mutable bytevector representing the unsigned bytes accumulated inport
so far.port
can be either open or closed.SOURCE NOTE: This is taken from r7rs.
If the
port
optional argument is not specified, then the value of theinput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual input port.Applicative
read
reads & returns the next parseable object from the given port, or theeof
if no objects remain. Ifread
finds and unparseable object in the port, an error is signaled. In that case, the remaining position in the port is unspecified.SOURCE NOTE: this is enumerated in the Kernel report but the text is still missing.
If the
port
optional argument is not specified, then the value of theoutput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual output port.Applicative
write
writes an external representation ofobject
to the specified port. This may be an output-only representation that can’t be read by applicativeread
in cases where the type ofobject
doen’t have a parseable external representation (e.g. combiners and environments). The result returned bywrite
is inert.write
is guaranteed to terminate even in the case of objects with shared or cyclic structure. In those caseswrite
will use special syntax to preserve sharing info.SOURCE NOTE: this is enumerated in the Kernel report but the text is still missing.
Applicative
write-simple
is likewrite
except that it doesn’t write sharing info. It will hang if handed a cyclic structure.SOURCE NOTE: this is taken from r7rs.
The primitive type predicate for type eof.
eof-object?
returns true iff all the objects inobjects
are of type eof.SOURCE NOTE: This is not in the report, the idea is from Scheme. The
eof-object?
name is also from Scheme, but this will probably be changed to justeof?
, for consistency with the other primitive type predicates.
If the
port
optional argument is not specified, then the value of theoutput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual output port.Applicative
newline
writes a newline to the specified port. The result returned bynewline
is inert.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
port
optional argument is not specified, then the value of theoutput-port
keyed dynamic variable is used. If the port is not a textual output port, or is closed, an error is signaled.Applicative
display
behaves likewrite
except that strings are not enclosed in double quotes and no character is escaped within those strings and character objects are output as if bywrite-char
instead ofwrite
. The result returned bydisplay
is inert.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
port
optional argument is not specified, then the value of theinput-port
keyed dynamic variable is used. If the port is closed or if it is not a textual input port, an error is signaled.Applicative
read-line
SOURCE NOTE: this is taken from r7rs.
If the
port
optional argument is not specified, then the value of theoutput-port
keyed dynamic variable is used. If the port is closed or if it is not an output port, an error is signaled.Applicative
flush-output-port
flushes any buffered data in the output port to the underlying object (file, socket, pipe, memory sector, device, etc). The result returned byflush-output-port
is inert.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
If the
port
optional argument is not specified, then the value of theoutput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual output port.Applicative
write-char
writes thechar
character (not an external representation of the character) to the specified port. The result returned bywrite-char
is inert.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
port
optional argument is not specified, then the value of theinput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual input port.Applicative
read-char
reads and returns a character (not an external representation of a character) from the specified port, or aneof
if the end of file was reached.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
port
optional argument is not specified, then the value of theinput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual input port.Applicative
peek-char
reads and returns a character (not an external representation of a character) from the specified port, or aneof
if the end of file was reached. The position of the port remains unchanged so that new call topeek-char
orread-char
on the same port return the same character.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
port
optional argument is not specified, then the value of theinput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual input port.Predicate
char-ready?
checks to see if a character is available in the specified port. If it returns true, then aread-char
orpeek-char
on that port is guaranteed not to block/hang. For now in klisp this is hardcoded to#t
because the code to do this is non-portable.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
port
optional argument is not specified, then the value of theoutput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a binary output port.Applicative
write-u8
writes the byte represented by the unsigned integeru8
, that should be between 0 and 255 inclusive, (not an external representation of byte) to the specified port. The result returned bywrite-u8
is inert.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
If the
port
optional argument is not specified, then the value of theinput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a binary input port.Applicative
read-u8
reads and returns a byte as an exact unsigned integer between 0 and 255 inclusive (not an external representation of a byte) from the specified port, or aneof
if the end of file was reached.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
If the
port
optional argument is not specified, then the value of theinput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a binary input port.Applicative
peek-u8
reads and returns a byte as an exact unsigned integer between 0 and 255 inclusive (not an external representation of a byte) from the specified port, or aneof
if the end of file was reached. The position of the port remains unchanged so that new call topeek-u8
orread-u8
on the same port return the same byte.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
If the
port
optional argument is not specified, then the value of theinput-port
keyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a binary input port.Predicate
u8-ready?
checks to see if a byte is available in the specified port. If it returns true, then aread-u8
orpeek-u8
on that port is guaranteed not to block/hang. For now in klisp this is hardcoded to#t
because the code to do this is non-portable.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
— Applicative: call-with-output-file (call-with-output-file string combiner)
These applicatives open file named in
string
for textual input/output respectively and call theircombiner
argument in a fresh empty environment passing it as a sole operand the opened port. When/if the combiner normally returns a value the port is closed and that value is returned as the result of the applicative.SOURCE NOTE: this is enumerated in the Kernel report but the text is still missing.
Applicative
load
opens the file namedstring
for textual input; reads immutable objects from the file until the end of the file is reached; evaluates those objects consecutively in the created environment. The result from applicativeload
is inert.Notice that if
string
is a relative path it is looked in the current directory (whatever that means in your OS, normally the directory from which the interpreted was run or the directory where the interpreter executable lives). klisp doesn’t track the directory from which the current code was read, so there’s in principle no way to load a file in the same directory as the currently executing code with a relative path. Seefind-required-filename
for a way to look for a file in a number of directories.SOURCE NOTE: load is enumerated in the Kernel report, but the description is not there yet. This seems like a sane way to define it, taking the description of
get-module
that there is in the report. The one detail that I think is still open, is whether to return#inert
(as is the case with klisp currently) or rather return the value of the last evaluation.
Applicative
require
looks forstring
following the algorithm described in applicativefind-required-filename
. If an appropriate file can’t be found, and error is signaled. Otherwise, the file is opened for textual input; immutable objects are read and acumulated until the end of file is found; those objects are evaluated in a fresh standard environment; the results of evaluation are discarded and the result from applicativerequire
is inert.Applicative
require
also registerstring
(as via applicativeregister-requirement!
) so that subsequent calls torequire
with exactly the samestring
will not cause any search or evaluation. The mechanism used for this can also be manipulated directly by the programmer via applicativesregistered-requirement?
,register-requirement!
,unregister-requirement!
, andfind-required-filename
.Applicative
require
is useful to load klisp libraries.SOURCE NOTE: require is taken from lua and r7rs.
— Applicative: register-requirement! (register-requirement! string)
— Applicative: unregister-requirement! (unregister-requirement! string)
— Applicative: find-required-filename (find-required-filename string)
string
should be non-empty.These applicatives control the underlying facilities used by
require
to register already required files. Predicateregistered-requirement?
returns true iffstring
is already registered.register-requirement!
marksstring
as registered (throws an error if it was already registered).unregister-requirement!
marksstring
as not being registered (throws an error if it wasn’t registered).find-required-filename
looks for an appropriate file forstring
using the algorithm described below.filename search in controlled by environment variable
KLISP_PATH
. This environment variable should be a list of templates separated with semicolons (“;”). Each template is a string that may contain embedded question mark characters (“?”) to be replaced withstring
. After replacements, each template represents the path to a file. All templates are probed in order, and the first to name an existing readable file is returned. If no template corresponds to an existing readable file, an error is signaled.NOTE: in the future there will be some mechanism to alter the search algorithm dinamically, in the meantime this environment variable is the only way to customize it.
SOURCE NOTE: this is not in Kernel, they are supplied per guideline G1b of the report (extensibility), so that klisp programs can easily duplicate the behaviour of
require
Applicative
get-module
creates a fresh standard environment; opens the file namedstring
for textual input; reads objects from the file until the end of the file is reached; evaluates those objects consecutively in the created environment; and, lastly, returns the created environment. If the optional argumentenvironment
is specified, the freshly created standard environment is augmented, prior to evaluating read expressions, by binding symbolmodule-parameters
to theenvironment
argument.