The second struct form shown in section 5.1 creates a new structure type that is a structure subtype of an existing base structure type. An instance of a structure subtype can always be used as an instance of the base structure type, but the subtype gets its own predicate procedure and may have its own fields in addition to the fields of the base type.
The t-expr expression in a subtyping struct form is evaluated when the struct expression is evaluated. The result of t-expr must be a structure type descriptor (returned as the first value of a struct expression that was evaluated earlier). The structure type associated with this descriptor is used as the base structure type for the new subtype. If the value of t-expr is not a structure type descriptor value, the exn:struct:struct-type exception is raised.
A structure subtype ``inherits'' the fields of its base type. If the base type has m fields and n fields are specified in the subtyping struct expression, the resulting structure type has m+n fields. This means that m+n field values must be provided to the subtype's constructor procedure. Values for the first m fields of a subtype instance are accessed with selector procedures for the original base type, and the last n are accessed with subtype-specific selectors. Subtype-specific selectors and setters for the first m fields are not created (so the number of values returned by a struct expression is always syntactically known, even though the actual base type is not known until run time).
The define-struct and let-struct macros have forms
that support subtyping:
(define-values (struct:s make-s s? s-field set-s-field! ) (struct (s t) (field )))
(define-struct (s t) (field ))
(let-struct (s t) (field )
body-expr )
(let-values ([(struct:s make-s s? s-field set-s-field! ) (struct (s t) (field ))])
body-expr )
Examples:
(define-struct cons-cell (car cdr))
(define x (make-cons-cell 1 2))
(define-struct (tagged-cons-cell struct:cons-cell) (tag))
(define z (make-tagged-cons-cell 3 4 't))
(cons-cell? z) ; => #t
(tagged-cons-cell? z) ; => #t
(tagged-cons-cell? x) ; => #f
(cons-cell-car z) ; => 3
(tagged-cons-cell-tag z) ; => 't