## Record types

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-type` is 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-type` is equivalent to the following definitions:

> - The `type-name` is bound to a representation of the record type itself.

> - The `constructor-name` is bound to a procedure that takes as many arguments as there are `field-tag`s in the `(`constructor-name` ...)` subform and returns a new `type-name` record. Fields whose tags are listed with `constructor-name` have the corresponding argument as their initial value. The initial values of all other fields are unspecified.

> - The `predicate-name` is a predicate that returns `#t` when given a value returned by `constructor-name` and `#f` for everything else.

> - Each `accessor-name` is a procedure that takes a record of type `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 a procedure that takes a record of type `type-name` and 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 `pare`s.

    (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. If the `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 module `parelib`, then the result is a class named `pare` with the internal JVM name `parelib$pare`. The `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 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 `<`name`>` (for example `<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.