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.
define-record-type feature is specified
which is implemented by many modern Scheme implementations.
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:
type-nameis bound to a representation of the record type itself.
constructor-nameis bound to a procedure that takes as many arguments as there are
field-tags in the
(subform and returns a new
type-namerecord. Fields whose tags are listed with
constructor-namehave the corresponding argument as their initial value. The initial values of all other fields are unspecified.
predicate-nameis a predicate that returns
#twhen given a value returned by
#ffor everything else.
accessor-nameis a procedure that takes a record of type
type-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.
modifier-nameis a procedure that takes a record of type
type-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
with two fields
(define-record-type pare (kons x y) pare? (x kar set-kar!) (y kdr))
The above defines
kons to be a constructor,
kdr to be accessors,
set-kar! to be a modifier,
pare? to be a predicate for
(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
Kawa compiles the record type into a nested class.
define-record-type appears at module level,
the result is a class that is a member of the module class.
For example if the above
pare class is define in a
parelib, then the result is a class
pare with the internal JVM name
define-record-type can appear inside a procedure,
in which case the result is an inner class.
The nested class has a name derived from
type-name. If the
type-name is valid Java class name,
that becomes the name of the Java class. If the
< (for example
is used, if possible, for the Java class name. Otherwise, the name
of the Java class is derived by "mangling" the
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.