(define-struct s (field
...field
)),
where s and field
are identifiers, creates a new
record datatype by adding these definitions to the environment:
(define-struct (s t) (field
...
field
))
is like (define-struct s ...), but the resulting datatype
is a subtype of t. The expression t must
evaluate to a structure descriptor (created by another
define-struct expression), otherwise exn:struct:super-type exception is raised.
If the datatype returned by t has
m fields, then a value created with
make-s will have m+n fields. The first m
fields are accessed with accessors from the datatype t, and the
rest are accessed with the s-field
accessors. A
value created with make-s will answer #t to both
s? and to the predicate that tests for type t. The
s? predicate will only return #t for
values created by make-s or by constructors for
subtypes of struct:s.
If define-struct is evaluated multiple times for the same structure type name, then each evaluation produces a new structure type.
(let-struct s (field
...field
) body)
and
(let-struct (s t) (field
...field
)
body) are like define-struct, but the generated procedures are only
bound within body.
If a define-struct statement is embedded within a closure, then it is transformed into a let-struct statement; all statements following the define-struct statement in the closure are moved into the body of the let-struct statement.
Examples:
(define orig-cons-cell? cons-cell?)
(define-struct cons-cell (car cdr))
(define y (make-cons-cell 1 2))
(cons-cell? y) ; => #t
(cons-cell? x) ; => #f, cons-cell? now checks a different type
(orig-cons-cell? x) ; => #t
(orig-cons-cell? y) ; => #f
(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? y) ; => #f
(cons-cell-car z) ; => 3
(tagged-cons-cell-tag z) ; => 't
(define-struct cons-cell (car cdr))
(define x (make-cons-cell 1 2))
(cons-cell? x) ; => #t
(cons-car x) ; => 1
(set-cons-car! x 5)
(cons-car x) ; => 5