chickadee » scheme » base » define-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 name>s 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 <pare>

 (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

}}