The define-record-type form can be used for creating new data
types, called record types. A predicate, constructor, and field
accessors and modifiers are defined for each record type.
The define-record-type feature is specified
by SRFI-9,
which is implemented by many modern Scheme implementations.
Syntax: define-record-type type-name (constructor-name field-tag ...) predicate-name (field-tag accessor-name [modifier-name]) ...
The form
define-record-typeis generative: each use creates a new record type that is distinct from all existing types, including other record types and Scheme's predefined types. Record-type definitions may only occur at top-level (there are two possible semantics for `internal' record-type definitions, generative and nongenerative, and no consensus as to which is better).An instance of
define-record-typeis equivalent to the following definitions:
The
type-nameis bound to a representation of the record type itself.
The
constructor-nameis bound to a procedure that takes as many arguments as there arefield-tags in the(subform and returns a newconstructor-name...)type-namerecord. Fields whose tags are listed withconstructor-namehave the corresponding argument as their initial value. The initial values of all other fields are unspecified.
The
predicate-nameis a predicate that returns#twhen given a value returned byconstructor-nameand#ffor everything else.
Each
accessor-nameis a procedure that takes a record of typetype-nameand 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-nameis a procedure that takes a record of typetype-nameand a value which becomes the new value of the corresponding field. The result (in Kawa) is the empty value#!void. It is an error to pass a modifier a first argument which is not a record of the appropriate type.Set!ing the value of any of these identifiers has no effect on the behavior of any of their original values.
Here is an example of how you can define a record type named pare
with two fields x and y:
(define-record-type pare (kons x y) pare? (x kar set-kar!) (y kdr))
The above 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 pares.
(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
The Kawa compiler creates a new Java class with a name derived from
the type-name.  If the type-name is valid Java class name,
that becomes the name of the Java class.  If the type-name has
the form < (for example name><pare>), then name
is used, if possible, for the Java class name.  Otherwise, the name
of the Java class is derived by "mangling" the type-name.
In any case, the package is the same as that of the surrounding module.
Kawa generates efficient code for the resulting functions, without needing to use run-time reflection.