make-record-type-descriptor(3scm) Scheme Programmer's Manual make-record-type-descriptor(3scm)

make-record-type-descriptor, record-type-descriptor?, record-type-opaque?, record-type-parent, record-type-sealed?, record-type-field-names, record-type-generative?, record-type-name, record-type-uid, record-field-mutable? - record-type construction and inspection

(import (rnrs))                     ;R6RS
(import (rnrs records procedural))  ;R6RS
(import (rnrs records inspection))  ;R6RS

; Procedural library
(make-record-type-descriptor name parent uid sealed? opaque? fields)
(record-type-descriptor? obj)
; Inspection library
(record-field-mutable? rtd number)
(record-type-field-names rtd)
(record-type-generative? rtd)
(record-type-name rtd)
(record-type-opaque? rtd)
(record-type-parent rtd)
(record-type-sealed? rtd)
(record-type-uid rtd)

The make-record-type-descriptor procedure returns a record-type descriptor, or rtd, representing a record type distinct from all built-in types and other record types.
Record names
The name argument must be a symbol. It names the record type, and is intended purely for informational purposes and may be used for printing by the underlying Scheme system.
Record inheritance
The parent argument must be either #f or an rtd. If it is an rtd, the returned record type extends the record type represented by parent. An exception with condition type &assertion(3scm) is raised if parent is sealed.
Unique identifiers
The uid argument must be either #f or a symbol. If uid is a symbol, the record-creation operation is nongenerative, i.e., a new record type is created only if no previous call to make-record-type-descriptor was made with the uid.
If uid is #f, the record-creation operation is generative, i.e., a new record type is created even if a previous call to make-record-type-descriptor was made with the same arguments.
If make-record-type-descriptor is called twice with the same uid symbol, the parent arguments in the two calls must be eqv?(3scm), the fields arguments equal?(3scm), the sealed? arguments boolean-equivalent (both #f or both true), and the opaque? arguments boolean-equivalent if the parents are not opaque. If these conditions are not met, an exception with condition type &assertion(3scm) is raised when the second call occurs. If they are met, the second call returns, without creating a new record type, the same record-type descriptor (in the sense of eqv?(3scm)) as the first call.
Sealed records
The sealed? flag must be a boolean. If true, the returned record type is sealed, i.e., it cannot be used as a parent.
Opaque records
The opaque? flag must be a boolean. If true, the record type is opaque. If passed an instance of the record type, record?(3scm) returns #f. Moreover, if record-rtd(3scm) is called with an instance of the record type, an exception with condition type &assertion(3scm) is raised. The record type is also opaque if an opaque parent is supplied. If opaque? is #f and an opaque parent is not supplied, the record is not opaque.
Record fields
The fields argument must be a vector of field specifiers. Each field specifier must be a list of the form (mutable name) or a list of the form (immutable name). Each name must be a symbol and names the corresponding field of the record type. The names need not be distinct.
A field identified as mutable may be modified, whereas, when a program attempts to obtain a mutator with record-mutator(3scm) for a field identified as immutable, an exception with condition type &assertion(3scm) is raised.
Where field order is relevant, e.g., for record construction and field access, the fields are considered to be ordered as specified, although no particular order is required for the actual representation of a record instance.
The specified fields are added to the parent fields, if any, to determine the complete set of fields of the returned record type.
If fields is modified after make-record-type-descriptor has been called, the effect on the returned rtd is unspecified.
Generative records
A generative record-type descriptor created by a call to make-record-type-descriptor is not eqv?(3scm) to any record-type descriptor (generative or nongenerative) created by another call to make-record-type-descriptor. A generative record-type descriptor is eqv?(3scm) only to itself, i.e., (eqv? rtd1 rtd2) iff (eq? rtd1 rtd2).
Also, two nongenerative record-type descriptors are eqv?(3scm) iff they were created by calls to make-record-type-descriptor with the same uid arguments.

The following procedures are used to inspect the rtd.

record-type-name
Returns the name of the record-type descriptor rtd.
record-type-parent
Returns the parent of the record-type descriptor rtd, or #f if it has none.
record-type-uid
Returns the uid of the record-type descriptor rtd, or #f if it has none.
An implementation may assign a generated uid to a record type even if the type is generative, so the return of a uid does not necessarily imply that the type is nongenerative.
record-type-generative?
Returns #t if rtd is generative, and #f if not.
record-type-sealed?
Returns #t if rtd is sealed, and #f if not.
record-type-opaque?
Returns #t if rtd is opaque, and #f if not.
record-type-field-names
Returns a vector of symbols naming the fields of the type represented by rtd (not including the fields of parent types) where the fields are ordered as in the fields argument.
The returned vector may be immutable. If the returned vector is modified, the effect on rtd is unspecified.
record-field-mutable?
Returns #t if the field specified by k of the type represented by rtd is mutable, and #f if not. The k argument is described in record-accessor(3scm).

make-record-type-descriptor
Returns a single value; a record type descriptor.
record-type-field-names
Returns a single value; a vector of symbols.
record-type-name
Returns a single value; a symbol.
record-type-parent
Returns a single value; a record type descriptor or #f.
record-type-uid
Returns a single value; a symbol or #f.
record-type-descriptor?, record-type-opaque?, record-type-sealed?, record-type-generative?, record-field-mutable?
These procedures return a single value; a boolean.

(define rtd-user
  (make-record-type-descriptor
    'user #f #f #f #f
    '#((immutable login) (immutable realname))))
(define rcd-user
  (make-record-constructor-descriptor
    rtd-user #f
    (lambda (p)
      (lambda (login realname)
        (p login realname)))))
(define make-user (record-constructor rcd-user))
(make-user 'lain "Lain Iwakura")
  => #[user login: lain realname: "Lain Iwakura"]

The syntactic layer is more commonly used in applications, see define-record-type(3scm). However, the procedural layer is needed to create new record types at runtime. The inspection layer is used to create, e.g., record printers.

A program that intends to use a record type descriptor to create a record also needs to create a record constructor descriptor with make-record-constructor-descriptor(3scm).

Users are encouraged to use symbol names constructed using the UUID namespace (for example, using the record-type name as a prefix) for the uid argument.

These procedures are unique to the R6RS record system. Equivalent procedures can be found in SRFI-237.

This procedure can raise exceptions with the following condition types:
&assertion (R6RS)
The wrong number of arguments was passed or an argument was outside its domain. The requirements on the arguments are described above.

define-record-type(3scm), make-record-constructor-descriptor(3scm), record-predicate(3scm), record-accessor(3scm), record-mutator(3scm)

R6RS

These procedures first appeared in R6RS as part of the new record system.

This page is part of the scheme-manpages project. It includes materials from the RnRS documents. More information can be found at https://weinholt.se/scheme/manpages/.

2023-08-02