10. ERR5RS standard libraries

ERR5RS has been superseded by the R7RS, so the libraries described below are now deprecated.

10.1. Load

The (err5rs load) library has been superseded by the (scheme load) library, and continues to exist only for backward compatibility.

Procedure load

(load filename)

Loads ERR5RS code from filename, evaluating each form as though it had been entered at the interactive read/eval/print loop.

Warning

The load procedure should be used only at an interactive top level and in files that will be loaded into an interactive top level. Calls to the load procedure have no effect at compile time, and should not appear in files that will be compiled separately; use the library and import syntaxes instead.

10.2. Records

The ERR5RS record facility described below incorporates all optional features of SRFI 99 and is otherwise identical to the facilities described by SRFI 99. SRFI 99 is itself an extension of SRFI 9, whose define-record-type syntax is identical to that defined by the R7RS.

When a procedure is said to be equivalent to an R6RS procedure, the equivalence holds only when all arguments have the properties required of them by the R6RS specification. ERR5RS does not mandate R6RS exception semantics for programs that violate the specification.

10.2.1. Procedural layer

This section describes the (err5rs records procedural) library.

Procedure make-rtd

(make-rtd name fieldspecs)

(make-rtd name fieldspecs parent-rtd)

(make-rtd name fieldspecs parent-rtd option …)

name is a symbol, which matters only to the rtd-name procedure of the inspection layer. fieldspecs is a vector of field specifiers, where each field specifier is one of

  • a symbol naming the (mutable) field;
  • a list of the form (mutable name), where name is a symbol naming the mutable field;
  • a list of the form (immutable name), where name is a symbol naming the immutable field.

The optional parent is an rtd or #f. It is an error for any of the symbols in fieldspecs to name more than one of the fields specified by fieldspecs, but the field names in fieldspecs may shadow field names in the parent rtd.

make-rtd returns an R6RS-compatible record-type descriptor.

Larceny allows the following optional arguments to follow the optional parent-rtd argument:

  • the symbol sealed means the new rtd cannot be used as the parent of other rtds;
  • the symbol opaque means the record? predicate will not recognize instances of the new rtd;
  • the symbol uid, followed by another symbol id, means the new rtd is non-generative with uid id; the semantics of this extension is the same as in the R6RS.

These Larceny-specific options may be used in any combination, giving Larceny's ERR5RS records the same expressive power as R6RS records, with which they are fully interoperable.

Procedure rtd?

(rtd? obj)

This predicate returns true if and only if its argument is a record-type descriptor. rtd? is equivalent to the record-type-descriptor? procedure of the R6RS.

Procedure rtd-constructor

(rtd-constructor rtd)

(rtd-constructor rtd fieldspecs)

rtd is a record-type descriptor, and fieldspecs is an optional vector of symbols.

If no fieldspecs argument is supplied, then rtd-constructor returns a procedure that expects one argument for each field of the record-type described by rtd and returns an instance of that record-type with its fields initialized to the corresponding arguments. Arguments that correspond to the fields of the record-type's parent (if any) come first.

If fieldspecs is supplied, then rtd-constructor returns a procedure that expects one argument for each element of fieldspecs and returns an instance of the record-type described by rtd with the named fields initialized to the corresponding arguments.

It is an error if some symbol occurs more than once in fieldspecs. Fields of a derived record-type shadow fields of the same name in its parent; the fieldspecs argument cannot be used to initialize a shadowed field.

Procedure rtd-predicate

(rtd-predicate rtd)

Equivalent to the record-predicate procedure of the R6RS.

Procedure rtd-accessor

(rtd-accessor rtd field)

field is a symbol that names a field of the record-type described by the record-type descriptor rtd. Returns a unary procedure that accepts instances of rtd (or any record-type that inherits from rtd) and returns the current value of the named field.

Fields in derived record-types shadow fields of the same name in a parent record-type.

Procedure rtd-mutator

(rtd-mutator rtd field)

field is a symbol that names a field of the record-type described by the record-type descriptor rtd. Returns a binary procedure that accepts instances of rtd (or any record-type that inherits from rtd) and a new value to be stored into the named field, performs that side effect, and returns an unspecified value.

Fields in derived record-types shadow fields of the same name in a parent record-type.

10.2.2. Inspection layer

This section describes the (err5rs records inspection) library.

Procedure record?

(record? obj)

Equivalent to its R6RS namesake.

Procedure record-rtd

(record-rtd record)

Equivalent to its R6RS namesake.

Procedure rtd-name

(rtd-name rtd)

Equivalent to the record-type-name procedure of the R6RS.

Procedure rtd-parent

(rtd-parent rtd)

Equivalent to the record-type-parent procedure of the R6RS.

Procedure rtd-field-names

(rtd-field-names rtd)

Equivalent to the record-type-field-names procedure of the R6RS. (That is, it returns a vector of the symbols that name the fields of the record-type represented by rtd, excluding the fields of parent record-types.)

Procedure rtd-all-field-names

(rtd-all-field-names rtd)

Returns a vector of the symbols that name the fields of the record-type represented by rtd, including the fields of its parent record-types, if any, with the fields of parent record-types coming before the fields of its children, with each subsequence in the same order as in the vectors that would be returned by calling rtd-field-names on rtd and on all its ancestral record-type descriptors.

Procedure rtd-field-mutable?

(rtd-field-mutable? rtd field)

rtd is a record-type descriptor, and field is a symbol naming a field of the record-type described by rtd. Returns #t if the named field is mutable; otherwise returns #f.

10.2.3. Syntactic layer

This section describes the (err5rs records syntactic) library.

The syntactic layer consists of SRFI 9 extended with single inheritance and (optional) implicit naming.

All ERR5RS record-type definitions are generative (unless Larceny's optional uid feature is used), but ERR5RS drops the SRFI 9 restriction to top level, mainly because the R6RS allows generative definitions wherever a definition may appear.

The syntax of an ERR5RS record-type definition is

    <definition>
      -> <record type definition>           ; addition to 7.1.6 in R5RS

    <record type definition>
      -> (define-record-type <type spec>
           <constructor spec>
           <predicate spec>
           <field spec> ...)

    <type spec>  -> <type name>
                 -> (<type name> <parent>)

    <constructor spec>
                 -> #f
                 -> #t
                 -> <constructor name>
                 -> (<constructor name> <field name> ...)

    <predicate spec>
                 -> #f
                 -> #t
                 -> <predicate name>

    <field spec> -> <field name>
                 -> (<field name>)
                 -> (<field name> <accessor name>)
                 -> (<field name> <accessor name> <mutator name>)

    <parent>           -> <expression>

    <type name>        -> <identifier>
    <constructor name> -> <identifier>
    <predicate name>   -> <identifier>
    <accessor name>    -> <identifier>
    <mutator name>     -> <identifier>
    <field name>       -> <identifier>

The semantics of a record type definition is the same as in SRFI 9: the record type definition macro-expands into a cluster of definitions that

  • defines the <type name> as the record-type descriptor for the new record-type;
  • defines a constructor for instances of the new record-type (unless the constructor spec is #f);
  • defines a predicate that recognizes instances of the new record-type and its subtypes (unless the predicate spec is #f);
  • defines an accessor for each field name;
  • defines a mutator for each mutable field name.

An ERR5RS record type definition extends SRFI 9 with the following additional options:

  • If a <parent> expression is specified, then it must evaluate to an rtd that serves as the parent record-type for the record-type being defined.
  • If #f is specified for the constructor or predicate, then no constructor or predicate procedure is defined. (This is useful when the record-type being defined will be used as an abstract base class.)
  • If #t is specified for the constructor or predicate, then the name of the constructor is the type name prefixed by make-, and the name of the predicate is the type name followed by a question mark (?).
  • If the constructor name is specified as #t or as an identifier, then the constructor's arguments correspond to the fields of the parent (if any) followed by the new fields added by this record-type definition.
  • If a field spec consists of a single identifier, then

    • the field is immutable;
    • the name of its accessor is the type name followed by a hyphen (-) followed by the field name.
  • If a field spec consists of a list of one identifier, then

    • the field is mutable;
    • the name of its accessor is the type name followed by a hyphen (-) followed by the field name;
    • the name of its mutator is the type name followed by a hyphen (-) followed by the field name followed by -set!.

10.2.4. Record identity

Two ERR5RS records with fields are eqv? if and only if they were created by the same (dynamic) call to some record constructor. Two ERR5RS records are eq? if and only if they are eqv?.

Apart from the usual constraint that equivalence according to eqv? implies equivalence according to equal?, the behavior of equal? on ERR5RS records is unspecified. (This is compatible with the R6RS.)

A define-record-type form macro-expands into code that calls make-rtd each time the expanded record-type definition is executed. Two ERR5RS record-type descriptors are eqv? if and only if they were created by the same (dynamic) call to make-rtd.