On this page:
struct
struct-field-index
define-struct
define-struct/ derived

4.1 Defining Structure Types: struct

+Programmer-Defined Datatypes in The Racket Guide introduces struct.

syntax

(struct id maybe-super (field ...)
        struct-option ...)
 
maybe-super = 
  | super-id
     
field = field-id
  | [field-id field-option ...]
     
struct-option = #:mutable
  | #:super super-expr
  | #:inspector inspector-expr
  | #:auto-value auto-expr
  | #:guard guard-expr
  | #:property prop-expr val-expr
  | #:transparent
  | #:prefab
  | #:constructor-name constructor-id
  | #:extra-constructor-name constructor-id
  | #:reflection-name symbol-expr
  | #:methods gen:name method-defs
  | #:omit-define-syntaxes
  | #:omit-define-values
     
field-option = #:mutable
  | #:auto
     
method-defs = (definition ...)
 
  gen:name : identifier?
Creates a new structure type (or uses a pre-existing structure type if #:prefab is specified), and binds transformers and variables related to the structure type.

A struct form with n fields defines up to 4+2n names:

If super-id is provided, it must have a transformer binding of the same sort bound to id (see Structure Type Transformer Binding), and it specifies a supertype for the structure type. Alternately, the #:super option can be used to specify an expression that must produce a structure type descriptor. See Structures for more information on structure subtypes and supertypes. If both super-id and #:super are provided, a syntax error is reported.

If the #:mutable option is specified for an individual field, then the field can be mutated in instances of the structure type, and a mutator procedure is bound. Supplying #:mutable as a struct-option is the same as supplying it for all fields. If #:mutable is specified as both a field-option and struct-option, a syntax error is reported.

The #:inspector, #:auto-value, and #:guard options specify an inspector, value for automatic fields, and guard procedure, respectively. See make-struct-type for more information on these attributes of a structure type. The #:property option, which is the only one that can be supplied multiple times, attaches a property value to the structure type; see Structure Type Properties for more information on properties. The #:transparent option is a shorthand for #:inspector #f.

Use the prop:procedure property to implement an applicable structure, use prop:evt to create a structure type whose instances are synchronizable events, and so on. By convention, property names start with prop:.

The #:prefab option obtains a prefab (pre-defined, globally shared) structure type, as opposed to creating a new structure type. Such a structure type is inherently transparent and cannot have a guard or properties, so using #:prefab with #:transparent, #:inspector, #:guard, or #:property is a syntax error. If a supertype is specified, it must also be a prefab structure type.

If constructor-id is supplied, then the transformer binding of id records constructor-id as the constructor binding; as a result, for example, struct-out includes constructor-id as an export. If constructor-id is supplied via #:extra-constructor-name and it is not id, applying object-name on the constructor produces the symbolic form of id rather than constructor-id. If constructor-id is supplied via #:constructor-name and it is not the same as id, then id does not serve as a constructor, and object-name on the constructor produces the symbolic form of constructor-id. Only one of #:extra-constructor-name and #:constructor-name can be provided within a struct form.

If #:reflection-name symbol-expr is provided, then symbol-expr must produce a symbol that is used to identify the structure type in reflective operations such as struct-type-info. It corresponds to the first argument of make-struct-type. Structure printing uses the reflective name, as do the various procedures that are bound by struct.

If #:methods gen:name method-defs is provided, then gen:name must be a transformer binding for the static information about a generic group produced by define-generics. The method-defs define the methods of gen:name. If any method of gen:name is not defined, then #f is used to signify that the structure type does not implement the particular method. At least one method definition must be provided if this keyword is used. A define/generic form may appear in method-defs. Auxiliary definitions and expressions may also appear in method-defs.

If the #:omit-define-syntaxes option is supplied, then id is not bound as a transformer. If the #:omit-define-values option is supplied, then none of the usual variables are bound, but id is bound. If both are supplied, then the struct form is equivalent to (begin).

If #:auto is supplied as a field-option, then the constructor procedure for the structure type does not accept an argument corresponding to the field. Instead, the structure type’s automatic value is used for the field, as specified by the #:auto-value option, or as defaults to #f when #:auto-value is not supplied. The field is mutable (e.g., through reflective operations), but a mutator procedure is bound only if #:mutable is specified.

If a field includes the #:auto option, then all fields after it must also include #:auto, otherwise a syntax error is reported. If any field-option or struct-option keyword is repeated, other than #:property, a syntax error is reported.

For serialization, see define-serializable-struct.

Examples:

> (struct posn (x y [z #:auto])
    #:auto-value 0
    #:transparent)
> (posn 1 2)

(posn 1 2 0)

> (posn? (posn 1 2))

#t

> (posn-y (posn 1 2))

2

(struct color-posn posn (hue) #:mutable)
(define cp (color-posn 1 2 "blue"))

 

> (color-posn-hue cp)

"blue"

> cp

(color-posn 1 2 0 ...)

> (set-posn-z! cp 3)

set-posn-z!: undefined;

 cannot reference undefined identifier

syntax

(struct-field-index field-id)

This form can only appear as an expression within a struct form; normally, it is used with #:property, especially for a property like prop:procedure. The result of a struct-field-index expression is an exact, non-negative integer that corresponds to the position within the structure declaration of the field named by field-id.

Examples:

> (struct mood-procedure (base rating)
    #:property prop:procedure (struct-field-index base))
(define happy+ (mood-procedure add1 10))
> (happy+ 2)

3

> (mood-procedure-rating happy+)

10

syntax

(define-struct id-maybe-super (field ...)
               struct-option ...)
 
id-maybe-super = id
  | (id super-id)
Like struct, except that the syntax for supplying a super-id is different, and a constructor-id that has a make- prefix on id is implicitly supplied via #:extra-constructor-name if neither #:extra-constructor-name nor #:constructor-name is provided.

This form is provided for backwards compatibility; struct is preferred.

Examples:

(define-struct posn (x y [z #:auto])
   #:auto-value 0
   #:transparent)
> (make-posn 1 2)

(posn 1 2 0)

> (posn? (make-posn 1 2))

#t

> (posn-y (make-posn 1 2))

2

syntax

(define-struct/derived (id . rest-form)
  id-maybe-super (field ...) struct-option ...)
The same as define-struct, but with an extra (id . rest-form) sub-form that is treated as the overall form for syntax-error reporting and otherwise ignored. The only constraint on the sub-form for error reporting is that it starts with id. The define-struct/derived form is intended for use by macros that expand to define-struct.

Examples:

> (define-syntax (define-xy-struct stx)
    (syntax-case stx ()
     [(ds name . rest)
      (with-syntax ([orig stx])
        #'(define-struct/derived orig name (x y) . rest))]))
> (define-xy-struct posn)
> (posn-x (make-posn 1 2))

1

> (define-xy-struct posn #:mutable)
> (set-posn-x! (make-posn 1 2) 0)
; this next line will cause an error due to a bad keyword
> (define-xy-struct posn #:bad-option)

eval:24:0: define-xy-struct: unrecognized

struct-specification keyword

  at: #:bad-option

  in: (define-xy-struct posn #:bad-option)