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 inobjectsare 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 iffportis 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
stringfor 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-fileandwith-output-from-fileis 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)
stringshould be the name/path for an existing file.Applicative
open-input-filecreates and returns a textual input port associated with the file represented withstring. Applicativeopen-binary-input-filecreates 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-fileis enumerated in the Kernel report but the text is still missing.open-binary-input-fileis from r7rs.
— Applicative: open-binary-output-file (open-binary-output-file string)
stringshould be the name/path for an existing file.Applicative
open-output-filecreates and returns a textual output port associated with the file represented withstring. Applicativeopen-binary-output-filecreates 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-fileandopen-binary-output-filetruncate 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-fileis enumerated in the Kernel report but the text is still missing.open-binary-output-fileis 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-stringreturns 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-bytevectorreturns 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-fileandclose-output-fileis 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-portis inert.SOURCE NOTE: this is from r7rs. The equivalent
close-input-fileandclose-output-fileare probably name errors and only retained here till the draft standard rectifies them.
portshould be a string output port.Applicative
get-output-stringreturns a freshly created mutable string representing the characters accumulated inportso far.portcan be either open or closed.SOURCE NOTE: This is taken from r7rs.
portshould be a bytevector output port.Applicative
get-output-bytevectorreturns a freshly created mutable bytevector representing the unsigned bytes accumulated inportso far.portcan be either open or closed.SOURCE NOTE: This is taken from r7rs.
If the
portoptional argument is not specified, then the value of theinput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual input port.Applicative
readreads & returns the next parseable object from the given port, or theeofif no objects remain. Ifreadfinds 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
portoptional argument is not specified, then the value of theoutput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual output port.Applicative
writewrites an external representation ofobjectto the specified port. This may be an output-only representation that can’t be read by applicativereadin cases where the type ofobjectdoen’t have a parseable external representation (e.g. combiners and environments). The result returned bywriteis inert.writeis guaranteed to terminate even in the case of objects with shared or cyclic structure. In those caseswritewill use special syntax to preserve sharing info.SOURCE NOTE: this is enumerated in the Kernel report but the text is still missing.
Applicative
write-simpleis likewriteexcept 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 inobjectsare 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
portoptional argument is not specified, then the value of theoutput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual output port.Applicative
newlinewrites a newline to the specified port. The result returned bynewlineis inert.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
portoptional argument is not specified, then the value of theoutput-portkeyed dynamic variable is used. If the port is not a textual output port, or is closed, an error is signaled.Applicative
displaybehaves likewriteexcept that strings are not enclosed in double quotes and no character is escaped within those strings and character objects are output as if bywrite-charinstead ofwrite. The result returned bydisplayis inert.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
portoptional argument is not specified, then the value of theinput-portkeyed dynamic variable is used. If the port is closed or if it is not a textual input port, an error is signaled.Applicative
read-lineSOURCE NOTE: this is taken from r7rs.
If the
portoptional argument is not specified, then the value of theoutput-portkeyed dynamic variable is used. If the port is closed or if it is not an output port, an error is signaled.Applicative
flush-output-portflushes any buffered data in the output port to the underlying object (file, socket, pipe, memory sector, device, etc). The result returned byflush-output-portis inert.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
If the
portoptional argument is not specified, then the value of theoutput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual output port.Applicative
write-charwrites thecharcharacter (not an external representation of the character) to the specified port. The result returned bywrite-charis inert.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
portoptional argument is not specified, then the value of theinput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual input port.Applicative
read-charreads and returns a character (not an external representation of a character) from the specified port, or aneofif the end of file was reached.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
portoptional argument is not specified, then the value of theinput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a textual input port.Applicative
peek-charreads and returns a character (not an external representation of a character) from the specified port, or aneofif the end of file was reached. The position of the port remains unchanged so that new call topeek-charorread-charon the same port return the same character.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
portoptional argument is not specified, then the value of theinput-portkeyed 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-charorpeek-charon that port is guaranteed not to block/hang. For now in klisp this is hardcoded to#tbecause the code to do this is non-portable.SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
If the
portoptional argument is not specified, then the value of theoutput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a binary output port.Applicative
write-u8writes 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-u8is inert.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
If the
portoptional argument is not specified, then the value of theinput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a binary input port.Applicative
read-u8reads 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 aneofif the end of file was reached.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
If the
portoptional argument is not specified, then the value of theinput-portkeyed dynamic variable is used. If the port is closed, an error is signaled. The port should be a binary input port.Applicative
peek-u8reads 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 aneofif the end of file was reached. The position of the port remains unchanged so that new call topeek-u8orread-u8on the same port return the same byte.SOURCE NOTE: this is missing from Kernel, it is taken from r7rs.
If the
portoptional argument is not specified, then the value of theinput-portkeyed 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-u8orpeek-u8on that port is guaranteed not to block/hang. For now in klisp this is hardcoded to#tbecause 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
stringfor textual input/output respectively and call theircombinerargument 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
loadopens the file namedstringfor 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 applicativeloadis inert.Notice that if
stringis 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-filenamefor 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-modulethat 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
requirelooks forstringfollowing 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 applicativerequireis inert.Applicative
requirealso registerstring(as via applicativeregister-requirement!) so that subsequent calls torequirewith exactly the samestringwill 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
requireis 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)
stringshould be non-empty.These applicatives control the underlying facilities used by
requireto register already required files. Predicateregistered-requirement?returns true iffstringis already registered.register-requirement!marksstringas registered (throws an error if it was already registered).unregister-requirement!marksstringas not being registered (throws an error if it wasn’t registered).find-required-filenamelooks for an appropriate file forstringusing 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-modulecreates a fresh standard environment; opens the file namedstringfor 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 argumentenvironmentis specified, the freshly created standard environment is augmented, prior to evaluating read expressions, by binding symbolmodule-parametersto theenvironmentargument.