7.6.2.8 R6RS Records

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 field of voxel.

  (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.