A structure type is a record datatype composing a number
of fields. A structure, an instance of a
structure type, is a first-class value that contains a value for each
field of the structure type. A structure instance is created with a
type-specific constructor procedure, and its field values are
accessed and changed with type-specific selector and setter
procedures. In addition, each structure type has a predicate
procedure that answers #t for instances of the structure type
and #f for any other value.
where s, t, and each field are identifiers. The
latter form is described in section 4.2. The optional
inspector-expr is explained in section 4.6.
A define-struct expression with nfields defines
4 + 2n names:
structure type descriptor
value that represents the new datatype. This value is
rarely used directly.
make-s, a constructor procedure that takes n
arguments and returns a new structure value.
s?, a predicate procedure that returns #t
for a value constructed by make-s (or the constructor for
a subtype; see section 4.2) and #f for any other
s-field, for each field, an accessor
procedure that takes a structure value and extracts the value for
set-s-field!, for each
field, a mutator procedure that takes a structure and a new
field value. The field value in the structure is destructively
updated with the new value, and void is returned.
s, a syntax binding that encapsulates information about
the structure type declaration. This binding is used to define
subtypes (see section 4.2). It also works with the
shared and match forms (see
and Chapter 19
in PLT MzLib: Libraries Manual). For detailed information
about the expansion-time information stored in s, see
Each time a define-struct expression is evaluated, a new
structure type is created with distinct constructor, predicate,
accessor, and mutator procedures. If the same define-struct
expression is evaluated twice, instances created by the constructor
returned by the first evaluation will answer #f to the
predicate returned by the second evaluation.
(cons-cell?x) ; => #t
(cons-cell-carx) ; => 1
(cons-cell-carx) ; => 5
(cons-cell?y) ; => #t
(cons-cell?x) ; => #f, cons-cell? now checks for a different type
(orig-cons-cell?x) ; => #t
(orig-cons-cell?y) ; => #f
The let-struct form binds structure identifiers in a
lexical scope; it does not support an inspector-expr.
The latter define-struct form shown in
section 4.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 identifier in a subtyping define-struct form must
be bound to syntax describing a structure type declaration. Normally,
it is the name of a structure type previously declared with
define-struct. The information associated with t is
used to access the base structure type for the new subtype.
A structure subtype ``inherits'' the fields of its base type. If the
base type has m fields, and if n fields are specified in
the subtyping define-struct expression, then the resulting
structure type has m + n fields. Consequently, 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
accessors and mutators for the first m fields are not created.
The make-struct-type procedure creates a new structure type in
the same way as the define-struct form of
section 4.1, but provides a more general interface. In
particular, the make-struct-type procedure supports structure
(make-struct-typename-symbol super-struct-type init-field-k
auto-field-k[auto-v prop-value-list inspector proc-spec]) creates a new
structure type. The name-symbol argument is used as the type
name. If super-struct-type is not #f, the new type is a
subtype of the corresponding structure type, as described in
The new structure type has
init-field-k + auto-field-k fields (in
addition to any fields from super-struct-type), but only
init-field-k constructor arguments (in addition to any
constructor arguments from super-struct-type). The remaining
fields are initialized with auto-v, which defaults to #f.
The prop-value-list argument is a list of pairs, where the
car of each pair is a structure type property descriptor, and
the cdr is an arbitrary value. The default is null. See
section 4.5 for more information about properties.
The inspector argument controls access to debugging information
about the structure type and its instances; see section 4.6
for more information.
The proc-spec argument can be #f, an exact
non-negative integer, or a procedure. The default is #f. If
an integer or procedure is provided, instances of the structure type
act as procedures. See section 4.4 for further information.
The result of make-struct-type is five values, which are
similar to the values produced by define-struct (see
a structure type descriptor,
a constructor procedure,
a predicate procedure,
an accessor procedure, which consumes a structure and a field
index between 0 (inclusive) and
init-field-k + auto-field-k (exclusive),
a mutator procedure, which consumes a structure, a field index,
and a field value.
Unlike define-struct, make-struct-type returns a single
accessor procedure and a single mutator procedure for all fields.
The make-struct-field-accessor and
make-struct-field-mutator procedures convert a type-specific
accessor or mutator returned by make-struct-type into a
field-specific accessor or mutator:
(make-struct-field-accessoraccessor-proc field-pos-k field-name-symbol)
returns a field accessor that is equivalent to
(lambda (s) (accessor-procsfield-pos-k))
The accessor-proc must be an accessor returned by
make-struct-type. The name of the resulting procedure for
debugging purposes is derived from field-name-symbol and
the name of accessor-proc's structure type.
(make-struct-field-mutatormutator-proc field-pos-k field-name-symbol)
returns a field mutator that is equivalent to
(lambda (sv) (mutator-procsfield-pos-kv))
The mutator-proc must be a mutator returned by
make-struct-type. The name of the resulting procedure for
debugging purposes is derived from field-name-symbol and
the name of mutator-proc's structure type.
If an integer or procedure is provided as the proc-spec argument
to make-struct-type (see section 4.3),
instances of the new structure type are procedures. In particular,
when procedure? is applied to the instance, the result
will be #t. When an instance is used in the function
position of an application expression, a procedure is extracted from
the instance and used to complete the procedure call.
If proc-spec is an integer, it designates a field within the
structure that should contain a procedure. The proc-spec
integer must be between 0 (inclusive) and
init-field-k + auto-field-k (exclusive).
The designated field becomes immutable, so that after an instance of
the structure is created, its procedure cannot be
changed. (Otherwise, the arity and name of the instance could change,
and such mutations are generally not allowed for procedures.) When
the instance is used as the procedure in an application expression,
the value of the designated field in the instance is used to complete
the procedure call.6 That
procedure receives all of the arguments from the application
expression. The procedure's name (see section 6.2.4) and arity
(see section 3.10.1) are also used for the name and arity of the
structure. If the value in the designated field is not a procedure,
then the instance behaves like (case-lambda) (i.e., a
procedure which does not accept any number of arguments).
(define (proc-annotationp) (ap-refp1))
(lambda (x) (+x1))
"adds 1 to its argument"))
(procedure?plus1) ; => #t
(annotated-proc?plus1) ; => #t
(plus110) ; => 11
(proc-annotationplus1) ; => "adds 1 to its argument"
If proc-spec is a procedure, it should accept at least one
argument. When an instance of the structure is used in an application
expression, the proc-spec procedure is called with the instance
as the first argument. The remaining arguments to the proc-spec
procedure are the arguments from the application expression. Thus, if
the application expression contained five arguments, proc-spec
is called with six arguments. The name of the instance (see
section 6.2.4) is unaffected by proc-spec, but the
instance's arity is determined by subtracting one from every possible
argument count of proc-spec. If proc-spec cannot accept
at least one argument, then the instance behaves like
If a structure type generates procedure instances, then subtypes of
the type also generate procedure instances. The instances behave the
same as instances of the original type, unless the subtype creation
also specifies a proc-spec, in which case the
proc-spec ``overrides'' the procedure behavior of the base
A structure type property
allows per-type information to be associated with a structure type
(as opposed to per-instance information associated with a structure
value). A property value is associated with a structure type through
the make-struct-type procedure (see
section 4.3). Subtypes inherit the property values
of their parent types, and only one value can be associated with a
type for any property.
(make-struct-type-propertyname-symbol) creates a new structure
type property and returns three values:
a structure property type descriptor, for use with
a predicate procedure, which takes an arbitrary value and
returns #t if the value is a descriptor or instance of a
structure type that has a value for the property, #f otherwise;
an accessor procedure, which returns the value associated with
structure type given its descriptor or one of its instances; the
structure type does not have a value for the property, or if any
other kind of value is provided, the exn:application:type exception is raised.
(struct-type-property?v) returns #t if v is a
structure type property descriptor value, #f otherwise.
An inspector provides access to structure fields and
structure type information without the normal field accessors and
mutators. Inspectors are primarily intended for use by debuggers.
When a structure type is created, an inspector can be supplied. The
given inspector is not the one that will control the new structure
type; instead, the given inspector's parent will control the type. By
using the parent of the given inspector, the structure type remains
opaque to ``peer'' code that cannot access the parent
inspector. Thus, an expression of the form
creates a structure type whose instances are opaque to peer code. In
contrast, the following idiom creates a structure type that is
transparent to peer code, because the supplied inspector is a newly
created child of the current inspector:
(define-structs (field···) (make-inspector))
The current-inspector parameter determines a default inspector
argument for new structure types. An alternate inspector can be
provided though the optional inspector-expr expression of the
define-struct form (see section 4.1), as shown
above, or through an optional inspector argument to
make-struct-type (see section 4.3).
(make-inspector[inspector]) returns a new inspector that is a
subinspector of inspector. If inspector is not provided,
the new inspector is a subinspector of the current inspector. Any
structure type controlled by the new inspector is also controlled by
its ancestor inspectors, but no other inspectors.
(inspector?v) returns #t if v is an inspector,
The struct-info and struct-type-info procedures provide
inspector-based access to structure and structure type information:
(struct-infov) returns two values:
struct-type: a structure type descriptor or #f;
the result is a structure type descriptor of the most specific type
for which v is an instance, and for which the current
inspector has control, or the result is #f if the current
inspector does not control any structure type for which the
struct is an instance.
skipped?: #f if the first result corresponds to
the most specific structure type of v, #t otherwise.
(struct-type-infostruct-type) returns six values that
provide information about the structure type descriptor
struct-type, assuming that the type is controlled by the
name-symbol: the structure type's name as a symbol;
field-k: the number of fields defined by the structure type (not
counting fields created by its ancestor types);
accessor-proc: an accessor procedure for the structure type,
like the one returned by make-struct-type;
mutator-proc: a mutator procedure for the structure type, like the one
returned by make-struct-type;
super-struct-type: a structure type descriptor for the
most specific ancestor of the type that is controlled by the
current inspector, or #f if no ancestor is controlled by
the current inspector;
skipped?: #f if the fifth result is the most
specific ancestor type or if the type has no supertype, #t
If the type for struct-type is not controlled by the current inspector,
the exn:application:mismatch exception is raised.
The following utility procedures work on all structure instances:
(struct->vectorv[opaque-v]) creates a vector representing
v. The first slot of the result vector contains a symbol of
the form struct:s. The each remaining slot contains
either the value of a field in v if it is accessible via the
current inspector, or opaque-v for a field that is not
accessible. A single opaque-v value is used in the vector for
contiguous inaccessible fields. (Consequently, the size of the vector
does not match the size of the struct if more than one field is
inaccessible.) The symbol '... is the default value for
(struct?v) returns #t if struct->vector
exposes any fields of v with the current inspector, #f
Two structure values are eqv? if and only if they are
eq?. Two structure values are equal? if and
only if they are instances of the same structure type, no fields are
opaque, and the results of applying struct->vector to the
structs are equal?. (Consequently, equal? testing
for structures depends on the current inspector.)
Each kind of value returned by define-struct and
make-struct-type has a recognizing predicate:
(struct-type?v) returns #t if v is a
structure type descriptor value, #f otherwise.
(struct-constructor-procedure?v) returns #t if
v is a constructor procedure generated by define-struct
or make-struct-type, #f otherwise.
(struct-predicate-procedure?v) returns #t if
v is a predicate procedure generated by define-struct or
make-struct-type, #f otherwise.
(struct-accessor-procedure?v) returns #t if v
is an accessor procedure generated by define-struct,
make-struct-type, or make-struct-field-accessor,
(struct-mutator-procedure?v) returns #t if v
is a mutator procedure generated by define-struct,
make-struct-type, or make-struct-field-mutator, #f
6 This procedure can be another structure
that acts as a procedure. The immutability of procedure fields
disallows cycles in the procedure graph, so that the procedure call
will eventually continue with a non-structure procedure.