Note: The following is based on a proposal posted by Pavel Curtis to rrrs-authors on 10 Sep 1989, and later re-posted by Norman Adams to comp.lang.scheme on 5 Feb 1992. The authorship and copyright status of the original text are unknown to me.
This document differs from the original proposal in that its record types are extensible, and that it specifies the type of record-type descriptors.
(make-record-type type-name field-names [parent-rtd])
Returns a "record-type descriptor", a value representing a new data type, disjoint from all others. The type-name argument must be a string, but is only used for debugging purposes (such as the printed representation of a record of the new type). The field-names argument is a list of symbols naming the "fields" of a record of the new type. It is an error if the list contains any duplicates.
If the parent-rtd argument is provided, then the new type will be a subtype of the type represented by parent-rtd, and the field names of the new type will include all the field names of the parent type. It is an error if the complete list of field names contains any duplicates.
Record-type descriptors are themselves records. In particular, record-type descriptors have a field printer that is either #f or a procedure. If the value of the field is a procedure, then the procedure will be called to print records of the type represented by the record-type descriptor. The procedure must accept two arguments: the record object to be printed and an output port.
(record-constructor rtd [field-names])
Returns a procedure for constructing new members of the type represented by rtd. The returned procedure accepts exactly as many arguments as there are symbols in the given list, field-names; these are used, in order, as the initial values of those fields in a new record, which is returned by the constructor procedure. The values of any fields not named in that list are unspecified. The field-names argument defaults to the list of field-names in the call to make-record-type that created the type represented by rtd; if the field-names argument is provided, it is an error if it contains any duplicates or any symbols not in the default list.
(record-predicate rtd)
Returns a procedure for testing membership in the type represented by rtd. The returned procedure accepts exactly one argument and returns a true value if the argument is a member of the indicated record type or one of its subtypes; it returns a false value otherwise.
(record-accessor rtd field-name)
Returns a procedure for reading the value of a particular field of a member of the type represented by rtd. The returned procedure accepts exactly one argument which must be a record of the appropriate type; it returns the current value of the field named by the symbol field-name in that record. The symbol field-name must be a member of the list of field-names in the call to make-record-type that created the type represented by rtd, or a member of the field-names of the parent type of the type represented by rtd.
(record-updater rtd field-name)
Returns a procedure for writing the value of a particular field of a member of the type represented by rtd. The returned procedure accepts exactly two arguments: first, a record of the appropriate type, and second, an arbitrary Scheme value; it modifies the field named by the symbol field-name in that record to contain the given value. The returned value of the updater procedure is unspecified. The symbol field-name must be a member of the list of field-names in the call to make-record-type that created the type represented by rtd, or a member of the field-names of the parent type of the type represented by rtd.
(record? obj)
Returns a true value if obj is a record of any type and a false value otherwise. Note that record? may be true of any Scheme value; of course, if it returns true for some particular value, then record-type-descriptor is applicable to that value and returns an appropriate descriptor.
(record-type-descriptor record)
Returns a record-type descriptor representing the type of the given record. That is, for example, if the returned descriptor were passed to record-predicate, the resulting predicate would return a true value when passed the given record. Note that it is not necessarily the case that the returned descriptor is the one that was passed to record-constructor in the call that created the constructor procedure that created the given record.
(record-type-name rtd)
Returns the type-name associated with the type represented by rtd. The returned value is eqv? to the type-name argument given in the call to make-record-type that created the type represented by rtd.
(record-type-field-names rtd)
Returns a list of the symbols naming the fields in members of the type represented by rtd.
(record-type-parent rtd)
Returns a record-type descriptor for the parent type of the type represented by rtd, if that type has a parent type, or a false value otherwise. The type represented by rtd has a parent type if the call to make-record-type that created rtd provided the parent-rtd argument.
(record-type-extends? rtd1 rtd2)
Returns a true value if the type represented by rtd1 is a subtype of the type represented by rtd2 and a false value otherwise. A type s is a subtype of a type t if s=t or if the parent type of s, if it exists, is a subtype of t.
Records are implemented on top of Larceny's structure data type: a record is a structure whose first slot contains a record-type-descriptor object.