6.12.1 Ports

Ports are the way that Guile performs input and output. Guile can read in characters or bytes from an input port, or write them out to an output port. Some ports support both interfaces.

There are a number of different port types implemented in Guile. File ports provide input and output over files, as you might imagine. For example, we might display a string to a file like this:

(let ((port (open-output-file "foo.txt")))
  (display "Hello, world!\n" port)
  (close-port port))

There are also string ports, for taking input from a string, or collecting output to a string; bytevector ports, for doing the same but using a bytevector as a source or sink of data; and soft ports, for arranging to call Scheme functions to provide input or handle output. See Types of Port.

Ports should be closed when they are not needed by calling close-port on them, as in the example above. This will make sure that any pending output is successfully written out to disk, in the case of a file port, or otherwise to whatever mutable store is backed by the port. Any error that occurs while writing out that buffered data would also be raised promptly at the close-port, and not later when the port is closed by the garbage collector. See Buffering, for more on buffered output.

Closing a port also releases any precious resource the file might have. Usually in Scheme a programmer doesn’t have to clean up after their data structures (see Memory Management and Garbage Collection), but most systems have strict limits on how many files can be open, both on a per-process and a system-wide basis. A program that uses many files should take care not to hit those limits. The same applies to similar system resources such as pipes and sockets.

Indeed for these reasons the above example is not the most idiomatic way to use ports. It is more common to acquire ports via procedures like call-with-output-file, which handle the close-port automatically:

(call-with-output-file "foo.txt"
  (lambda (port)
    (display "Hello, world!\n" port)))

Finally, all ports have associated input and output buffers, as appropriate. Buffering is a common strategy to limit the overhead of small reads and writes: without buffering, each character fetched from a file would involve at least one call into the kernel, and maybe more depending on the character and the encoding. Instead, Guile will batch reads and writes into internal buffers. However, sometimes you want to make output on a port show up immediately. See Buffering, for more on interfaces to control port buffering.

Scheme Procedure: port? x
C Function: scm_port_p (x)

Return a boolean indicating whether x is a port.

Scheme Procedure: input-port? x
C Function: scm_input_port_p (x)

Return #t if x is an input port, otherwise return #f. Any object satisfying this predicate also satisfies port?.

Scheme Procedure: output-port? x
C Function: scm_output_port_p (x)

Return #t if x is an output port, otherwise return #f. Any object satisfying this predicate also satisfies port?.

Scheme Procedure: close-port port
C Function: scm_close_port (port)

Close the specified port object. Return #t if it successfully closes a port or #f if it was already closed. An exception may be raised if an error occurs, for example when flushing buffered output. See Buffering, for more on buffered output. See close, for a procedure which can close file descriptors.

Scheme Procedure: port-closed? port
C Function: scm_port_closed_p (port)

Return #t if port is closed or #f if it is open.

Scheme Procedure: call-with-port port proc

Call proc, passing it port and closing port upon exit of proc. Return the return values of proc.