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