The manual sections below describe Guile’s implementation of R6RS records, which provide support for user-defined data types. The R6RS records API provides a superset of the features provided by Guile’s “native” records, as well as those of the SRFI-9 records API; See Records, and SRFI-9 Records, for a description of those interfaces.
As with SRFI-9 and Guile’s native records, R6RS records are constructed using a record-type descriptor that specifies attributes like the record’s name, its fields, and the mutability of those fields.
R6RS records extend this framework to support single inheritance via the specification of a “parent” type for a record type at definition time. Accessors and mutator procedures for the fields of a parent type may be applied to records of a subtype of this parent. A record type may be sealed, in which case it cannot be used as the parent of another record type.
The inheritance mechanism for record types also informs the process of initializing the fields of a record and its parents. Constructor procedures that generate new instances of a record type are obtained from a record constructor descriptor, which encapsulates the record-type descriptor of the record to be constructed along with a protocol procedure that defines how constructors for record subtypes delegate to the constructors of their parent types.
A protocol is a procedure used by the record system at construction time to bind arguments to the fields of the record being constructed. The protocol procedure is passed a procedure n that accepts the arguments required to construct the record’s parent type; this procedure, when invoked, will return a procedure p that accepts the arguments required to construct a new instance of the record type itself and returns a new instance of the record type.
The protocol should in turn return a procedure that uses n and p to initialize the fields of the record type and its parent type(s). This procedure will be the constructor returned by
As a trivial example, consider the hypothetical record type
pixel, which encapsulates an x-y location on a screen, and
voxel, which has
pixel as its parent type and stores an
additional coordinate. The following protocol produces a constructor
procedure that accepts all three coordinates, uses the first two to
initialize the fields of
pixel, and binds the third to the single
(lambda (n) (lambda (x y z) (let ((p (n x y))) (p z))))
It may be helpful to think of protocols as “constructor factories” that produce chains of delegating constructors glued together by the helper procedure n.
An R6RS record type may be declared to be nongenerative via the use of a unique generated or user-supplied symbol—or uid—such that subsequent record type declarations with the same uid and attributes will return the previously-declared record-type descriptor.
R6RS record types may also be declared to be opaque, in which case
the various predicates and introspection procedures defined in
(rnrs records introspection) will behave as if records of this
type are not records at all.
Note that while the R6RS records API shares much of its namespace with both the SRFI-9 and native Guile records APIs, it is not currently compatible with either.