Record-type definitions

Record-type definitions are used to introduce new data types, called record types. Like other definitions, they can appear either at the outermost level or in a body. The values of a record type are called records and are aggregations of zero or more fields, each of which holds a single location. A predicate, a constructor, and field accessors and mutators are defined for each record type.

(define-record-type {name} {constructor} {pred} {field} ... ) syntax
Syntax: name and pred are identifiers. The constructor is of the form

({constructor name} {field name} ...)

and each field is either of the form

({field name} {accessor name})

or of the form

({field name} {accessor name} {modifier name})

It is an error for the same identifier to occur more than once as a field name. It is also an error for the same identifier to occur more than once as an accessor or mutator name.

The define-record-type construct is generative: each use creates a new record type that is distinct from all existing types, including Scheme's predefined types and other record types -- even record types of the same name or structure.

An instance of define-record-type is equivalent to the following definitions:

  • name is bound to a representation of the record type itself. This may be a run-time object or a purely syntactic representation. The representation is not utilized in this report, but it serves as a means to identify the record type for use by further language extensions.
  • {constructor name} is bound to a procedure that takes as many arguments as there are field names in the ({constructor name} ...) subexpression and returns a new record of type name. Fields whose names are listed with constructor name have the corresponding argument as their initial value. The initial values of all other fields are unspecified. It is an error for a field name to appear in constructor but not as a field name.
  • pred is bound to a predicate that returns #t when given a value returned by the procedure bound to {constructor name} and #f for everything else.
  • Each {accessor name} is bound to a procedure that takes a record of type name and returns the current value of the corresponding field. It is an error to pass an accessor a value which is not a record of the appropriate type.
  • Each {modifier name} is bound to a procedure that takes a record of type name and a value which becomes the new value of the corresponding field; an unspecified value is returned. It is an error to pass a modifier a first argument which is not a record of the appropriate type.

For instance, the following record-type definition

(define-record-type (kons x y) pare? (x kar set-kar!) (y kdr))

defines kons to be a constructor, kar and kdr to be accessors, set-kar! to be a modifier, and pare? to be a predicate for instances of <pare>.

(pare? (kons 1 2)) ==> #t (pare? (cons 1 2)) ==> #f (kar (kons 1 2)) ==> 1 (kdr (kons 1 2)) ==> 2 (let ((k (kons 1 2))) (set-kar! k 3) (kar k)) ==> 3

husk-scheme online documentation rev 3.2 (2021.03.04)