|• Port and threads:|
|• Common port operations:|
|• File ports:|
|• String ports:|
|• Coding-aware ports:|
A port class. A port is Scheme’s way of abstraction of I/O channel. Gauche extends a port in number of ways so that it can be used in wide range of applications.
R7RS defines textual and binary ports. In Gauche, most ports can mix both text I/O and binary I/O. It is cleaner to think the two is distinct, for they are sources/sinks of different types of objects and you don’t need to mix textual and binary I/O.
In practice, however, a port is often a tap to an
untyped pool of bytes and you may want to decide
interpret it later. One example is the standard I/O; in Unix-like
environment, it’s up to the program to use pre-opened ports
for textual or binary I/O. R7RS defines the initial ports
current-input-port etc. are textual ports; in Gauche,
you can use either way.
Some ports can be used to convert a data stream from one format
to another; one of such applications is character code conversion
ports, provided by
(see Character code conversion, for details).
There are also a ports with special functionality. A coding-aware port (see Coding-aware ports) recognizes a special "magic comment" in the file to know which character encoding the file is written. Virtual ports (see Virtual ports) allows you to program the behavior of the port in Scheme.
When Gauche is compiled with thread support,
the builtin port operations locks the port, so that port access
from multiple threads will be serialized.
(It is required by SRFI-18, BTW).
Here, "builtin port operations" are the port access functions
that takes a port and does some I/O or query on it,
with-* procedures do not
lock the port during calling the given procedures, since the
procedure may pass the reference of the port to the other thread,
and Gauche wouldn’t know if that’s the case.
This means you don’t need to be too paranoia to worry about ports under multithreaded environment. However, keep it in mind that this locking mechanism is meant to be a safety net from breaking the port’s internal state, and not to be a general mutex mechanism. It assumes port accesses rarely conflict, and uses spin lock to reduce the overhead of majority cases. If you know there will be more than one thread accessing the same port, you should use explicit mutex to avoid conflicts.
Executes thunk, while making the calling thread hold the exclusive lock of port during the dynamic extent of thunk.
Calls of the builtin port functions during the lock is held would bypass mutex operations and yield better performance.
Note that the lock is held during the dynamic extent of thunk;
so, if thunk invokes a continuation captured outside of
with-port-locking, the lock is released. If the continuation
captured within thunk is invoked afterwards, the lock is re-acquired.
With-port-locking may be nested. The lock is valid during
the outermost call of
Note that this procedure uses the port’s built-in lock mechanism which uses busy wait when port access conflicts. It should be used only for avoiding fine-grain lock overhead; use explicit mutex if you know there will be conflicts.
Returns true if obj is a port, an input port and an output port,
Port? is not listed in the
R5RS standard procedures, but mentioned in the "Disjointness of Types"
Returns true if obj is a port and it is already closed. A closed port can’t be reopened.
[R7RS] Returns the current input, output and error output port, respectively.
R7RS defines that the initial values of these ports are textual ports. In Gauche, initial ports can handle both textual and binary I/O.
Values of the current ports can be temporarily changed by
(see Parameters), though you might want the convenience procedures
in typical cases.
(use gauche.parameter) (let1 os (open-output-string) (parameterize ((current-output-port os)) (display "foo")) (get-output-string os)) ⇒ "foo"
Returns standard i/o ports at the time the program started.
These ports are the default values
You can also change value of these procedures by
but note that (1)
current-*-ports are initialized before
the program execution, so changing values of
won’t affect them, and (2) changing values these procedures only affect
Scheme-world, and does not change system-level stdio file descriptors
low-level libraries referring.
Calls thunk. During evaluation of thunk, the current input port, current output port and current error port are set to port, respectively. Note that port won’t be closed after thunk is executed.
Does the above three functions at once.
Calls thunk while the current input, output, and error ports are
set to iport, oport, and eport, respectively.
You may pass
#f to any port argument(s) if you don’t need
to alter the port(s).
Note that port won’t be closed after thunk is executed.
(Unfortunately, recent Scheme standards added a similar
which does close the port. See below.)
Closes the port.
Close-port works both input and
output ports, while
work only for the respective ports and throws an error if another type
of port is passed.
close-port would suffice; having those three
is merely for historical reason.
R6RS and R7RS support all three.
Calls proc with one argument, port. After proc returns,
or it throws an uncaptured error, port is closed. Value(s) returned
from proc will be the return value(s) of
Returns the type of port in one of the symbols
Returns the name of port. If the port is associated to a file, it is the name of the file. Otherwise, it is some description of the port.
If port is type of file port (i.e.
file), these procedures gets and sets the port’s
buffering mode. For input ports, the port buffering mode may be
either one of
For output ports,
port-buffering, it may be
See File ports, for explanation of those modes.
port-buffering is applied to ports other than file ports,
#f. If the setter of port-buffering is
applied to ports other than file ports, it signals an error.
Returns the current line count of port. This information is only available on file-based port, and as long as you’re doing sequential character I/O on it. Otherwise, this returns -1.
Returns an integer file descriptor, if the port is associated
to the system file I/O. Returns
If the given port allows random access, this procedure sets
the read/write pointer of the port according to the given offset
and whence, then returns the updated offset (number of bytes
from the beginning of the data). If port is not random-accessible,
#f is returned. In the current version, file ports and
input string ports are fully random-accessible. You can only query
the current byte offset of output string ports.
Note that port position is represented by byte count, not character count.
It is allowed to seek after the data if port is an output file port. See POSIX lseek(2) document for details of the behavior. For input file port and input string port, you can’t seek after the data.
The whence argument must be a small integer that represents from where offset should be counted. The following constant values are defined.
Offset represents the byte count from the beginning of the data. This is the default behavior when whence is omitted.
Offset represents the byte count relative to the current read/write pointer. If you pass 0 to offset, you can get the current port position without changing it.
Offset represents the byte count relative to the end of the data.
Returns the current read/write pointer of port in byte count,
if port is random-accessible. Returns
This is equivalent to the following call:
(port-seek port 0 SEEK_CUR)
Note on the names:
Port-seek is called
output-port-position on some implementations.
Port-tell is called
set-file-position!. Some implementations have
port-position for different functionality.
file-position, but it is not suitable
for us since port need not be a file port.
tell reflects POSIX name, and with Gauche naming convention
we could use
sys-tell; however, port
deals with higher level of abstraction than system calls, so I dropped
those names, and adopted new names.
Copies data from an input port src to an output port dst, until eof is read from src.
The keyword argument unit may be zero, a positive exact integer,
byte or a symbol
char, to specify the unit
of copying. If it is an integer, a buffer of the size
(in case of zero, a system default size) is used to copy,
using block I/O. Generally it is the fastest if you copy
between normal files. If unit is a symbol
the copying is done byte by byte, using C-version of
write-byte. If unit is a symbol
the copying is done character by character, using C-version of
If nonnegative integer is given to the keyword argument size,
it specifies the maximum amount of data to be copied. If unit
is a symbol
char, size specifies the number of characters.
Otherwise, size specifies the number of bytes.
Returns number of characters copied when unit is a symbol
char. Otherwise, returns number of bytes copied.
[R7RS+] Opens a file filename for input or output, and returns an input or output port associated with it, respectively.
The keyword arguments specify precise behavior.
This keyword argument can be specified only for
specifies the action when the filename already exists.
One of the following value can be given.
The existing file is truncated. This is the default behavior.
The output data will be appended to the existing file.
The output data will overwrite the existing content. If the output data is shorter than the existing file, the rest of existing file remains.
An error is signaled.
No action is taken, and the function returns
This keyword argument specifies the action when filename does not exist.
An error is signaled. This is the default behavior of
A file is created. This is the default behavior of
The check of file existence and creation is done atomically; you can
exclusively create the file by specifying
if-exists, along this option.
You can’t specify this value for
No action is taken, and the function returns
This argument specifies the buffering mode. The following values are
The port’s buffering mode can be get/set by
(see Common port operations).
Buffer the data as much as possible. This is the default mode.
No buffering is done. Every time the data is written (to an output port) or read (from an input port), the underlying system call is used. Process’s standard error port is opened in this mode by default.
This is valid only for output ports. The written data is buffered, but the buffer is flushed whenever a newline character is written. This is suitable for interactive output port. Process’s standard output port is opened in this mode by default. (Note that this differs from the line buffering mode of C stdio, which flushes the buffer as well when input is requested from the same file descriptor.)
This is valid only for input ports. This is almost the same as the mode
:full, except that
read-uvector may return less data
than requested if the requested amount of data is not immediately available.
read-uvector waits the entire data to be
read). This is suitable for the port connected to a pipe or network.
This argument specifies the type of the file.
The file is opened in "character" (or "text") mode.
The file is opened in "binary" mode.
In the current version, this argument is ignored and all files are opened in binary mode. It doesn’t make difference in the Unix platforms.
This argument specifies character encoding of the file. The argument is a string or a symbol that names a character encoding scheme (CES).
open-input-file, it can be a wildcard CES (e.g.
to guess the file’s encoding heuristically
(see Autodetecting the encoding scheme),
#t, in which case we assume the input file itself has magic
encoding comment and use
(see Coding-aware ports).
If this argument is given, Gauche automatically loads
gauche.charconv module and converts the input/output characters
as you read to or write from the port.
See Supported character encoding schemes, for the details of
character encoding schemes.
This argument may be used with the encoding argument to specify the buffer size of character encoding conversion. It is passed as a buffer-size argument of the conversion port constructors (see Conversion ports).
Usually you don’t need to give this argument; but if you need to guess the input file encoding, larger buffer size may work better since guessing routine can have more data before deciding the encoding.
By combination of if-exists and if-does-not-exist flags, you can implement various actions:
(open-output-file "foo" :if-exists :error) ⇒ ;opens "foo" exclusively, or error (open-output-file "foo" :if-exists #f) ⇒ ;opens "foo" exclusively, or returns #f (open-output-file "foo" :if-exists :append :if-does-not-exist :error) ⇒ ;opens "foo" for append only if it already exists
To check the existence of a file without opening it,
file-exists? (see File stats).
Note for portability: Some Scheme implementations (e.g. STk) allows
you to specify a command to filename and reads from, or
writes to, the subprocess standard input/output. Some other scripting
languages (e.g. Perl) have similar features. In Gauche,
open-output-file strictly operates
on files (what the underlying OS thinks as files).
However, you can use “process ports” to invoke
other command in a subprocess and to communicate it.
See Process ports, for details.
[R7RS+] Opens a file specified by string for input/output, and call proc with one argument, the file port. When proc returns, or an error is signaled from proc that is not captured within proc, the file is closed.
The keyword arguments have the same meanings of
open-output-file’s. Note that
if you specify
#f to if-exists and/or if-does-not-exist,
proc may receive
#f instead of a port object when
the file is not opened.
Returns the value(s)
[R7RS] Opens a file specified by string for input or output and makes the opened port as the current input or output port, then calls thunk. The file is closed when thunk returns or an error is signaled from thunk that is not captured within thunk.
Returns the value(s)
The keyword arguments have the same
except that when
#f is given to if-exists and
if-does-not-exist and the opening port is failed,
thunk isn’t called at all and
#f is returned
as the result of
Notes on semantics of closing file ports:
R7RS states, in the description of
call-with-port et al.,
that "If proc does not return, then the port will
not be closed automatically unless it is possible
to prove that the port will never again be used for read or write
Gauche’s implementation slightly misses this criteria; the mere fact that an uncaptured error is thrown in proc does not prove the port will never be used. Nevertheless, it is very difficult to think the situation that you can do meaningful operation on the port after such an error is signaled; you’d have no idea what kind of state the port is in. In practical programs, you should capture error explicitly inside proc if you still want to do some meaningful operation with the port.
Note that if a continuation captured outside
et al. is invoked inside proc, the port is not closed.
It is possible that the control returns later into the proc,
if a continuation is captured in it (e.g. coroutines).
The low-level exceptions (see Handling exceptions)
also doesn’t ensure closing the port.
Creates and returns an input or output port on top of the given
file descriptor. Buffering specifies the buffering mode
as described in
open-input-file entry above; the default
:full. Name is used for the created port’s name
and returned by
port-name. A boolean flag
specifies whether fd should be closed when the port is closed.
Interface to the system call
Atomically closes the file descriptor associated to toport,
creates a copy of the file descriptor associated to fromport,
and sets the new file descriptor to toport.
Both toport and fromport must be file ports.
Before the original file descriptor of toport is closed,
any buffered output (when toport is an output port) is flushed,
and any buffered input (when toport is an input port) is discarded.
‘Copy’ means that, even the two file descriptors differ in their values,
they both point to the same system’s open file table entry. For example
they share the current file position; after port-fd-dup!,
if you call
port-seek on fromport, the change is also visible
from toport, and vice versa. Note that this ’sharing’ is in the
system-level; if either toport or fromport is buffered,
the buffered contents are not shared.
This procedure is mainly intended for programs that needs to control open file descriptors explicitly; e.g. a daemon process would want to redirect its I/O to a harmless device such as /dev/null, and a shell process would want to set up file descriptors before executing the child process.
String ports are the ports that you can read from or write to memory.
Creates an input string port that has the content string.
This is a more efficient way to access a string in order
rather than using
string-ref with incremental index.
(define p (open-input-string "foo x")) (read p) ⇒ foo (read-char p) ⇒ #\space (read-char p) ⇒ #\x (read-char p) ⇒ #<eof> (read-char p) ⇒ #<eof>
Port must be an input string port. Returns the remaining content of the input port. The internal pointer of port isn’t moved, so the subsequent read from port isn’t affected. If port has already reached to EOF, a null string is returned.
(define p (open-input-string "abc\ndef")) (read-line p) ⇒ "abc" (get-remaining-input-string p) ⇒ "def" (read-char p) ⇒ #\d (read-line p) ⇒ "ef" (get-remaining-input-string p) ⇒ ""
Creates an output string port. Anything written to the
port is accumulated in the buffer, and can be obtained
as a string by
This is a far more efficient way to construct a string
sequentially than pre-allocate a string and fill it with
Takes an output string port
port and returns a string
that has been accumulated to
port so far.
If a byte data has been written to the port, this function
re-scans the buffer to see if it can consist a complete string;
if not, an incomplete string is returned.
This doesn’t affect the port’s operation, so you can keep
accumulating content to port after calling
These utility functions are trivially defined as follows. The interface is parallel to the file port version.
(define (call-with-output-string proc) (let ((out (open-output-string))) (proc out) (get-output-string out))) (define (call-with-input-string str proc) (let ((in (open-input-string str))) (proc in))) (define (with-output-to-string thunk) (let ((out (open-output-string))) (with-output-to-port out thunk) (get-output-string out))) (define (with-input-from-string str thunk) (with-input-from-port (open-input-string str) thunk))
(define (call-with-string-io str proc) (let ((out (open-output-string)) (in (open-input-string str))) (proc in out) (get-output-string out))) (define (with-string-io str thunk) (with-output-to-string (lambda () (with-input-from-string str thunk))))
These convenience functions cover common idioms using string ports.
(write-to-string obj writer) ≡ (with-output-to-string (lambda () (writer obj))) (read-from-string string) ≡ (with-input-from-string string read)
The default value of writer is the procedure
The default values of start and end is 0 and
the length of string.
Portability note: Common Lisp has these functions, with
different optional arguments.
read-from-string without optional argument.
A coding-aware port is a special type of procedural input port that
is used by
load to read a program source. The port recognizes
the magic comment to specify the character encoding of the
program source, such as
;; -*- coding: utf-8 -*-, and makes
an appropriate character encoding conversion.
See Multibyte scripts for the details of coding magic comment.
Takes an input port and returns an input coding aware port, which basically just pass through the data from iport to its reader. However, if a magic comment appears within the first two lines of data from iport, the coding aware port applies the necessary character encoding conversion to the rest of the data as they are read.
The passed port, iport, is "owned" by the created coding-aware port. That is, when the coding-aware port is closed, iport is also closed. The content read from iport is buffered in the coding-aware port, so other code shouldn’t read from iport.
By default, Gauche’s
load uses a coding aware port to read
the program source, so that the coding magic comment works for
the Gauche source programs (see Loading Scheme file).
However, since the mechanism itself
is independent from
load, you can use this port for
other purposes; it is particularly useful to write a function
that processes Scheme source programs which may have the coding
For the input-related procedures, the optional iport argument must be an input port, and when omitted, the current input port is assumed.
|• Reading data:|
|• Reader lexical mode:|
|• Read-time constructor:|
|• Input utility functions:|
[R7RS] Reads an S-expression from iport and returns it. Gauche recognizes the lexical structure specified in R7RS, and some additional lexical structures listed in Lexical structure.
If iport has already reached to the end of file, an eof object is returned.
The procedure reads up to the last character that consists the S-expression,
and leaves the rest in the port. It’s not like CommonLisp’s
which consumes whitespaces after S-expression by default.
These procedures are defined in srfi-38 to recognize shared substructure
#n#). Gauche’s builtin
the srfi-38 notation, so these are just synonyms to
are only provided for srfi-38 compatibility.
[R7RS] Reads one character from iport and returns it. If iport has already reached to the end, returns an eof object. If the byte stream in iport doesn’t consist a valid character, the behavior is undefined. (In future, a port will have a option to deal with invalid characters).
[R7RS] Reads one character in iport and returns it, keeping the character in the port. If the byte stream in iport doesn’t consist a valid character, the behavior is undefined. (In future, a port will have a option to deal with invalid characters).
Reads one byte from an input port iport, and returns it as an integer in the range between 0 and 255. If iport has already reached EOF, an eof object is returned.
This is called
read-u8 in R7RS.
Peeks one byte at the head of an input port iport, and returns it as an integer in the range between 0 and 255. If iport has already reached EOF, an eof object is returned.
This is called
peek-u8 in R7RS.
[R7RS+] Reads one line (a sequence of characters terminated by newline or EOF) and returns a string. The terminating newline is not included. This function recognizes popular line terminators (LF only, CRLF, and CR only). If iport has already reached EOF, an eof object is returned.
If a byte sequence is read from iport
which doesn’t constitute a valid character in the native encoding,
read-line signals an error by default. However, if a true value
is given to the argument allow-byte-string?,
read-line returns a byte string (incomplete string) in such case,
without reporting an error.
It is particularly useful if you read from a source whose
character encoding is not yet known; for example, to read XML document,
you need to check the first line to see if there is a charset parameter
so that you can then use an appropriate character conversion port.
This optional argument is Gauche’s extension to R7RS.
[R7RS] Read nchars characters, or as many characters as available before EOF, and returns a string that consists of those characters. If the input has already reached EOF, an eof object is returned.
This procedure is deprecated - use
(see Uvector block I/O).
Reads nbytes bytes from iport, and returns an incomplete string consisted by those bytes. The size of returned string may shorter than nbytes when iport doesn’t have enough bytes to fill. If nbytes is zero, a null string is always returned.
If iport has already reached EOF, an eof object is returned.
If iport is a file port, the behavior of
differs by the buffering mode of the port (See File ports, for
the detail explanation of buffering modes).
read-blockwaits until nbytes data is read, except it reads EOF.
read-blockreturns shorter string than nbytes even if it doesn’t reach EOF, but the entire data is not available immediately.
If you want to write a chunk of bytes to a port,
you can use either
display if the data is in string,
gauche.uvector (see Uvector block I/O)
if the data is in uniform vector.
[R7RS] Returns an EOF object.
[R7RS] Returns true if obj is an EOF object.
If a character is ready to be read from port, returns
For now, this procedure actually checks only if next byte is
immediately available from port. If the next byte is a part of
a multibyte character, the attempt to read the whole character may block,
#t on the port.
(It is unlikely to happen in usual situation, but theoretically it can.
If you concern, use
read-uvector to read the input as a byte
sequence, then use input string port to read characters.)
If one byte (octet) is ready to be read from port, returns
In R7RS, this procedure is called
Get/set the reader lexical mode. Changing this parameter switches behavior of the reader concerning some corner cases of the lexical syntax, where legacy Gauche syntax and R7RS syntax aren’t compatible.
In general, you don’t need to change this parameter directly. The lexical syntax matters at the read-time, while changing this parameter happens at the execution-time; unless you know the exact timing when each phase occurs, you might not get what you want.
The hash-bang directive
indirectly affects this parameter; the first one sets the reader
legacy, and the second one to
The command-line argument
-fwarn-legacy sets the default
reader mode to
Change to this parameter during
load is delimited within that
load is done, the value of this parameter is reset
to the value when
load is started.
The parameter takes one of the following symbols as a value.
This is the default mode. It tries to find a reasonable compromise between two syntax.
In string literals, hex escape sequence
is first interpreted as R7RS lexical syntax. If the syntax doesn’t
conform R7RS hex escape, it is interpreted as legacy Gauche hex escape
syntax. For example,
"\x30;a" is read as
the hex escape sequence including the terminating semicolon is read
as R7RS hex escape sequence. It also reads
"0a", for the legacy Gauche hex escape always takes two hexadecimal
digits without the terminator. With this mode, you can use R7RS
hex escape syntax for the new code, and yet almost all legacy Gauche
code can be read without a problem.
However, if the legacy code has a semicolon followed by hex escape,
it is interpreted as R7RS syntax and the incompatibility arises.
Identifiers beginning with a colon are read as keywords, as they’ve always been.
strict R7RS behavior, you need to use vertical-bar escaping
|:foo|) to have symbols beginning with colon.
Note that this incompatibility will be addressed in the future version
of Gauche, when keywords become a subtype of symbols.
Strict R7RS compatible mode.
When the reader encounters the hash-bang directive
the rest of file is read with this mode.
In this mode, Gauche’s extended lexical syntax will raise an error. Identifiers beginning with a colon are read as symbols.
Use this mode to read R7RS code with maximum compatibility.
The reader works as the legacy Gauche (version 0.9.3.3 and before).
When the reader encounters the hash-bang directive
the rest of file is read with this mode.
This only matters when you want to read two-digit hex escape
followed by semicolon as a character plus a semicolon, e.g.
"0;a" instead of
We expect such a sequence rarely appears in the code,
but if you dump a data in a string literal format, you may
have such sequence (especially in incomplete string literals).
The reader works as the
but warns if it reads legacy hex-escape syntax.
This mode is default when
argument is given to
This is useful to check if you have any incompatible escape sequence in your code.
Read-time constructor, defined in SRFI-10, provides an easy way to create an external representation of user-defined structures.
#,(tag arg …)
[SRFI-10] Gauche maintains a global table that associates a tag (symbol) to a constructor procedure.
When the reader encounters this syntax, it reads arg …, finds a reader constructor associated with tag, and calls the constructor with arg … as arguments, then inserts the value returned by the constructor as the result of reading the syntax.
Note that this syntax is processed inside the reader—the evaluator doesn’t see any of args, but only sees the object the reader returns.
[SRFI-10] Associates a reader constructor procedure with tag.
(define-reader-ctor 'pi (lambda () (* (atan 1) 4))) #,(pi) ⇒ 3.141592653589793 '(#,(pi)) ⇒ (3.141592653589793) (define-reader-ctor 'hash (lambda (type . pairs) (let ((tab (make-hash-table type))) (for-each (lambda (pair) (hash-table-put! tab (car pair) (cdr pair))) pairs) tab))) (define table #,(hash eq? (foo . bar) (duh . dah) (bum . bom))) table ⇒ #<hash-table eq? 0x80f9398> (hash-table-get table 'duh) ⇒ dah
write-object method (see Output),
it is easy to make a user-defined class written in the form
it can be read back:
(define-class <point> () ((x :init-value 0 :init-keyword :x) (y :init-value 0 :init-keyword :y))) (define-method write-object ((p <point>) out) (format out "#,(<point> ~s ~s)" (ref p 'x) (ref p 'y))) (define-reader-ctor '<point> (lambda (x y) (make <point> :x x :y y)))
NOTE: The extent of the effect of
is not specified in SRFI-10, and might pose a compatibility problem
among implementations that support SRFI-10.
(In fact, the very existence of
up to an implementation choice.)
In Gauche, at least for the time being,
take effects as soon as the form is compiled and evaluated. Since
Gauche compiles and evaluates each toplevel form in order, tag
define-reader-ctor can be used immediately after that.
However, it doesn’t work if the call of
the use of tag is enclosed in a
begin form, for the entire
begin form is compiled at once before being evaluated.
Other implementations may require to read the entire file before
define-reader-ctor call effective. If so, it
effectively prevents one from using
the defined tag in the same file. It is desirable to separate
the call of
define-reader-ctor and the use of tag
in the different files if possible.
Another issue about the current
define-reader-ctor is that
it modifies the global table of Gauche system, hence it is not modular.
The code written by different people might use the same tags,
and yield an unexpected result. In future versions, Gauche may
have some way to encapsulate the scope of tag, although
the author doesn’t have clear idea yet.
Generally useful input procedures. The API is taken from scsh and STk.
port->string reads port
until EOF and returns the accumulated data as a string.
port->list applies reader on port repeatedly, until
reader returns an EOF, then returns the list of objects
Note that port isn’t closed.
port->string-list is a
port->sexp-list is a
If the input contains an octet sequence that’s not form a valid
character in the Gauche’s native character encoding,
port->string-list may return
If you want to deal with binary data, consider using
gauche.uvector (see Uvector block I/O).
Convenient iterators over the input read by reader.
Since these procedures are not really about ports,
they are superseded by
generator-map, respectively. See Folding generated values,
for the details.
We provide these only for the backward compatibility.
|• Layers of output routines:|
|• Output controls:|
|• Object output:|
|• Formatting output:|
|• Low-level output:|
Gauche has quite a few output procedures which may confuse newcomers. The following table will help to understand how to use those procedures:
Procedures that write out Scheme objects. Although there exist more low-level procedures, these are regarded as a basic layer of output routines, since it works on a generic Scheme object as a single unit. They come in two flavors:
write-simple–these are to produce external representation of Scheme objects, which can be generally read back by
readwithout losing information as much as possible1. The external representation of most Scheme objects are the ones you write literal data in program, so this is the default way of writing Scheme objects out.
newline. These are to produce plain-text output suitable for human readers.
To produce output in specific width, alignment, etc:
This corresponds to C’s
Procedures that deal with raw data.
You can control several aspects of Lisp structure output via
<write-controls> object. The object output routines
write, display) and the high-level output routines
format) can take optional write-controls.
The following example may give you some ideas on what write controls can do:
(write '(1 10 100 1000) (make-write-controls :print-base 16 :print-radix #t)) prints (#x1 #xa #x64 #x3e8) (write (iota 100) (make-write-controls :print-length 5)) prints (0 1 2 3 4 ...)
make-write-controls procedure returns a write-controls object,
which has the following slots (those slot names are taken from Common Lisp’s
print control variables):
If this slot has a nonnegative integer, it determines the maximum number
of items displayed for lists and vectors (including uniform vectors).
If the sequence has more elements than the limit,
... is printed
in place. If this slot is
#f (default), sequence will be written
If this slot has a nonnegative integer, it determines the maximum depth
of the structure (lists and vectors) to be displayed. If the structure
has deeper node, it will be printed as
If this slot is
#f (default), no depth limit is enforced.
This slot must have an integer between 2 and 36, inclusive, and specifies the radix used to print exact numbers. The default value is 10.
This slot must have a boolean value. If it is true, radix prefix
is always printed before exact numbers. The default value is
A write-controls object is immutable. If you need a controls object
with a slight variation of an existing controls object,
Returns a write-controls object.
Returns a copy of another write-controls object controls. If keyword arguments are given, those values override the original values.
Note: The high-level output procedures can be recursively called
write-object method. In that case, the write controls
of the root output call will be automatically inherited to the
recursive output calls to the same port.
For the following procedures, the optional port argument must be an output port, and when omitted, the current output port is assumed.
Some procedures take port/controls argument, which can be either
an output port or
<write-controls> object. For example,
takes up to two such optional arguments; that is, you can call it
(write obj port),
(write obj controls),
(write obj port controls)
(write obj controls port). When omitted, the port is assumed
to be the current output port, and the controls is assumed to be the default
write-family procedures are used to write an
external representation of Scheme object,
which can be read back by
read procedure. The three
procedures differ in a way to handle shared or circular structures.
Write is circular-safe; that is, it uses datum label notation
#n#) to show cycles. It does not use datum label
notation for non-circular structures that are merely shared
(see the second example).
(let1 x (list 1) (set-cdr! x x) ; create a cycle (write x)) ⇒ shows #0=(1 . #0#) (let1 x (list 1) (write (list x x))) ⇒ shows ((1) (1))
Write-shared is also circular-safe, and it also shows
shared structures using datum labels. Use this if you need
to preserve topology of a graph structure.
(let1 x (list 1) (write (list x x))) ⇒ shows (#0=(1) #0#)
write-simple writes out the object recursively
without taking account of shared or circular structures. This is fast,
for it doesn’t need to scan the structure before actually writing out.
However, it won’t stop when a circular structure is passed.
When these procedures encounter an object of
a user-defined class, they call the generic function
Write has been in Scheme standards, but
handling of circular structures hasn’t been specified until R7RS.
In fact, until Gauche 0.9.4,
write diverged for circular structures.
SRFI-38 introduced the datum-label notation and
to produce such notation, and Gauche supported it.
R7RS clarified this issue, and Gauche 0.9.4 followed.
These are aliases of
Gauche has been used the name
write* for long, which is
taken from STklos. SRFI-38 defines
write/ss. These names are kept for the backward compatibility.
New code should use
[R7RS] Produces a human-friendly representation of an object obj to the output port.
If obj contains cycles,
display uses datum-label notation.
display encounters an object of
a user-defined class, it calls the generic function
(display "\"Mahalo\", he said.") ⇒ shows "Mahalo", he said. (let ((x (list "imua"))) (set-cdr! x x) (display x)) ⇒ shows #0=(imua . #0#)
Displays exprs (using
display) to the current output port,
then writes a newline.
You can customize how the object is printed out by this method.
Writes a newline character to port.
This is equivalent to
(write-char #\newline port),
(display "\n" port). It is kept for a historical reason.
Format arg … according to string.
This function is a subset of CommonLisp’s
with a bit of extension. It is also a superset of SRFI-28,
Basic format strings (SRFI-28).
The dest argument specifies the destination; if it is an output port, the
formatted result is written to it; if it is
the result is written to the current output port;
if it is
#f, the formatted result is returned as a string.
Dest can be omitted, as SRFI-28
it has the same effects as giving
#f to the dest.
The controls argument is
(see Output controls), which affects the output of
~a. This is Gauche’s extension.
(The unusual function signature of
is for the convenience; both dest
and controls are optional and they can appear in either order.)
string is a string that contains format directives.
A format directive is a character sequence begins with tilde, ‘
and ends with some specific characters. A format directive takes
the corresponding arg and formats it. The rest of string is
copied to the output as is.
(format #f "the answer is ~s" 42) ⇒ "the answer is 42"
The format directive can take one or more parameters, separated by comma characters. A parameter may be an integer or a character; if it is a character, it should be preceded by a quote character. Parameter can be omitted, in such case the system default value is used. The interpretation of the parameters depends on the format directive.
Furthermore, a format directive can take two
additional flags: atmark ‘
@’ and colon ‘
:’. One or
both of them may modify the behavior of the format directive.
Those flags must be placed immediately before the directive
If a character ‘
v’ or ‘
V’ is in the place of the
parameter, the value of the parameter is taken from the format’s
argument. The argument must be either an integer, a character, or
#f (indicating that the parameter is effectively omitted).
A format directive
~s, with two parameters, 10 and 2.
A format directive
~a, with 12 for the first parameter and
a character ‘
*’ for the fourth parameter. The second and
third parameters are omitted.
A format directive
~d, with 10 for the first parameter and
A format directive
~x, whose first and second parameter will
be taken from the arguments.
The following is a complete list of the supported format directives. Either upper case or lower case character can be used for the format directive; usually they have no distinction, except noted.
Ascii output. The corresponding argument is printed by
If an integer mincol is given, it specifies the minimum number
of characters to be output; if the formatted result is shorter than
mincol, a whitespace is padded to the right (i.e. the result
is left justified).
The colinc, minpad and padchar parameters control, if given, further padding. A character padchar replaces the padding character for the whitespace. If an integer minpad is given and greater than 0, at least minpad padding character is used, regardless of the resulting width. If an integer colinc is given, the padding character is added (after minpad) in chunk of colinc characters, until the entire width exceeds mincol.
If atmark-flag is given, the format result is right justified, i.e. padding is added to the left.
The maxcol parameter, if given, limits the maximum number of characters
to be written. If the length of formatted string exceeds
maxcol, only maxcol characters are written.
If colon-flag is given as well and the length of formatted string
exceeds maxcol, maxcol - 4 characters are written and
a string “
...” is attached after it.
(format #f "|~a|" "oops") ⇒ "|oops|" (format #f "|~10a|" "oops") ⇒ "|oops |" (format #f "|~10@a|" "oops") ⇒ "| oops|" (format #f "|~10,,,'*@a|" "oops") ⇒ "|******oops|" (format #f "|~,,,,10a|" '(abc def ghi jkl)) ⇒ "|(abc def gh|" (format #f "|~,,,,10:a|" '(abc def ghi jkl)) ⇒ "|(abc de ...|"
S-expression output. The corresponding argument is printed
write. The semantics of parameters and flags are the same
(format #f "|~s|" "oops") ⇒ "|\"oops\"|" (format #f "|~10s|" "oops") ⇒ "|\"oops\" |" (format #f "|~10@s|" "oops") ⇒ "| \"oops\"|" (format #f "|~10,,,'*@s|" "oops") ⇒ "|****\"oops\"|"
Decimal output. The argument is formatted as an decimal integer.
If the argument is not an integer, all parameters are ignored
(after processing ‘
v’ parameters) and
it is formatted by
If an integer parameter mincol is given, it specifies minimum width of the formatted result; if the result is shorter than it, padchar is padded on the left (i.e. the result is right justified). The default of padchar is a whitespace.
(format #f "|~d|" 12345) ⇒ "|12345|" (format #f "|~10d|" 12345) ⇒ "| 12345|" (format #f "|~10,'0d|" 12345) ⇒ "|0000012345|"
If atmark-flag is given, the sign ‘
+’ is printed for the
If colon-flag is given, every interval-th digit of
the result is grouped and commachar is inserted between them.
The default of commachar is ‘
,’, and the default of
interval is 3.
(format #f "|~:d|" 12345) ⇒ "|12,345|" (format #f "|~,,'_,4:d|" -12345678) ⇒ "|-1234_5678|"
Binary output. The argument is formatted as a binary integer.
The semantics of parameters and flags are the same as
Octal output. The argument is formatted as an octal integer.
The semantics of parameters and flags are the same as
The argument is formatted as a hexadecimal integer.
X’ is used, upper case alphabets are used for
the digits larger than 10. If ‘
x’ is used, lower case
alphabets are used.
The semantics of parameters and flags are the same as
(format #f "~8,'0x" 259847592) ⇒ "0f7cf5a8" (format #f "~8,'0X" 259847592) ⇒ "0F7CF5A8"
Moves the argument counter count times forward, effectively skips
next count arguments. The default value of count is 1,
hence skip the next argument. If a colon-flag is given, moves the argument
counter backwards, e.g.
~:* makes the next directive to process
last argument again. If an atmark-flag is given, count specifies
absolute position of the arguments, starting from 0.
[R7RS] Write a single character char to the output port port.
Write a byte byte to the port. byte must be an exact integer in range between 0 and 255.
This procedure is called
write-u8 in R7RS.
Output the buffered data in port, or all ports, respectively.
The function "flush" is called in variety of ways on the various
force-output (Scsh, SCM),
flush-output (Gambit), or
flush is taken from STk and STklos.
R7RS calls this
In a sense, this is somewhat similar to
what is called “serialization” or “marshalling” in other programming
language; you can
write out a generic Scheme object on disk or
to wire, and
read it to get an object equivalent to the original
one. In Lisp-family languages, this is called read/write invariance
and is a built-in feature.
Note that some objects do not have this invariance
in nature, so sometimes you need to make your own serializer/marshaller.