On this page:
top
up

5.1Defining Structure Types: struct πŸ”— i

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

syntax

( struct idmaybe-super(field...)
struct-option...)
maybe-super =
| super-id
field = field-id
| [field-idfield-option...]
struct-option = #:mutable
| #:supersuper-expr
| #:inspectorinspector-expr
| #:auto-valueauto-expr
| #:guardguard-expr
| #:propertyprop-exprval-expr
| #:propertiesprop-list-expr
| #:transparent
| #:prefab
| #:sealed
| #:authentic
| #:namename-id
| #:extra-namename-id
| #:constructor-nameconstructor-id
| #:extra-constructor-nameconstructor-id
| #:reflection-namesymbol-expr
| #:methodsgen:name-idmethod-defs
| #:omit-define-syntaxes
| #:omit-define-values
field-option = #:mutable
| #:auto
method-defs = (definition...)
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:

  • struct:id, a structure type descriptor value that represents the structure type.

  • constructor-id (which defaults to id), a constructor procedure that takes m arguments and returns a new instance of the structure type, where m is the number of fields that do not include an #:auto option.

  • name-id (which defaults to id), a transformer binding that encapsulates information about the structure type declaration. This binding is used to define subtypes, and it also works with the shared and match forms. For detailed information about the binding of name-id, see Structure Type Transformer Binding.

    The constructor-id and name-id can be the same, in which case name-id performs both roles. In that case, the expansion of name-id as an expression produces an otherwise inaccessible identifier that is bound to the constructor procedure; the expanded identifier has a 'constructor-for property whose value is an identifier that is free-identifier=? to name-id as well as a syntax property accessible via syntax-procedure-alias-property with an identifier that is free-identifier=? to name-id.

  • id?, a predicate procedure that returns #t for instances of the structure type (constructed by constructor-id or the constructor for a subtype) and #f for any other value.

  • id-field-id, for each field; an accessor procedure that takes an instance of the structure type and extracts the value for the corresponding field.

  • set-id-field-id!, for each field that includes a #:mutable option, or when the #:mutable option is specified as a struct-option; a mutator procedure that takes an instance of the structure type and a new field value. The structure is destructively updated with the new value, and #<void> is returned.

If super-id is provided, it must have a transformer binding of the same sort bound to name-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.

Examples:
> (struct document(authortitlecontent))
> (struct bookdocument(publisher))
> (struct paper(journal)#:superstruct:document)

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.

Examples:
> (struct cell([content#:mutable])#:transparent)
> (define a-cell(cell0))
> (set-cell-content!a-cell1)

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 can be supplied multiple times, attaches a property value to the structure type; see Structure Type Properties for more information on properties. The #:properties option, which can be supplied multiple times, accepts multiple properties and their values as an association list. The #:transparent option is a shorthand for #:inspector#f.

Examples:
> (struct point(xy)#:inspector#f)
> (point35)

(point 3 5)

> (struct celsius(temp)
#:guard(λ (tempname)
(unless (and (real? temp)(>= temp-273.15))
(error "not a valid temperature"))
temp))
> (celsius-275)

not a valid temperature

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 non-sealed, and it cannot have a guard or properties, so using #:prefab with #:transparent, #:inspector, #:guard, #:property, #:sealed, #:authentic, or #:methods is a syntax error. If a supertype is specified, it must also be a prefab structure type.

Examples:
> (struct prefab-point(xy)#:prefab)
> (prefab-point12)

'#s(prefab-point 1 2)

> (prefab-point?#s(prefab-point12))

#t

The #:sealed option is a shorthand for #:propertyprop:sealed #t, which prevents the structure type from being used as the supertype of another structure type. See prop:sealed for more information.

The #:authentic option is a shorthand for #:propertyprop:authentic #t, which prevents instances of the structure type from being impersonated (see impersonate-struct ), chaperoned (see chaperone-struct ), or acquiring a non-flat contract (see struct/c ). See prop:authentic for more information. If a supertype is specified, it must also have the prop:authentic property.

If name-id is supplied via #:extra-name and it is not id, then both name-id and id are bound to information about the structure type. Only one of #:extra-name and #:name can be provided within a struct form, and #:extra-name cannot be combined with #:omit-define-syntaxes.

Examples:
> (struct ghost(colorname)#:prefab#:extra-nameGHOST)
> (match (ghost'red'blinky)
[(GHOSTcn)c])

'red

If constructor-id is supplied, then the transformer binding of name-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 name-id, then name-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.

Examples:
> (struct color(rgb)#:constructor-name-color)
> (struct rectangle(whcolor)#:extra-constructor-namerect)
> (rectangle1350(-color192157235))

#<rectangle>

> (rect5037(-color35183252))

#<rectangle>

If #:reflection-namesymbol-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 .

Examples:
> (struct circle(radius)#:reflection-name'<circle>)
> (circle15)

#<<circle>>

> (circle-radius"bad")

<circle>-radius: contract violation

expected: <circle>?

given: "bad"

If #:methodsgen:name-idmethod-defs is provided (potentially multiple times), then gen:name-id must be a transformer binding for the static information about a generic interface produced by define-generics . The method-defs define the methods of the gen:name-id interface. A define/generic form or auxiliary definitions and expressions may also appear in method-defs.

Examples:
> (struct constant-stream(val)
#:methodsgen:stream
(constant-stream-valstream ))
> (stream-ref (constant-stream'forever)0)

'forever

> (stream-ref (constant-stream'forever)50)

'forever

If the #:omit-define-syntaxes option is supplied, then name-id (and id, if #:extra-name is specified) 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 ).

Examples:
> (struct square(side)#:omit-define-syntaxes)
> (match (square5)
;fails to match because syntax is omitted
[(struct squarex)x])

eval:28:0: match: square does not refer to a structure

definition

at: square

in: (struct square x)

> (struct ellipse(widthheight)#:omit-define-values)
> ellipse-width

ellipse-width: undefined;

cannot reference an identifier before its definition

in module: top-level

Expressions supplied to #:auto-value are evaluated once and shared between every instance of the structure type. In particular, updates to a mutable #:auto-value affect all current and future instances.

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.

Examples:
(struct posn(xy[z#:auto#:mutable])
#:auto-value0
#:transparent)
> (posn12)

(posn 1 2 0)

> (posn?(posn12))

#t

> (posn-y(posn12))

2

> (posn-z(posn12))

0

(struct color-posnposn(hue)#:mutable)
(define cp(color-posn12"blue"))
> (color-posn-huecp)

"blue"

> cp

(color-posn 1 2 0 ...)

> (set-posn-z!cp3)

For serialization, see define-serializable-struct .

Changed in version 6.9.0.4 of package base: Added #:authentic.
Changed in version 8.0.0.7: Added #:sealed.
Changed in version 8.17.0.4: Added #:properties.

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(baserating)
(define happy+(mood-procedureadd1 10))
> (happy+2)

3

> (mood-procedure-ratinghappy+)

10

syntax

( define-struct id-maybe-super(field...)
struct-option...)
id-maybe-super = id
| (idsuper-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(xy[z#:auto])
#:auto-value0
#:transparent)
> (make-posn12)

(posn 1 2 0)

> (posn?(make-posn12))

#t

> (posn-y(make-posn12))

2

syntax

( struct/derived (id. rest-form)
id(field...)struct-option...)
(struct/derived (id. rest-form)
idsuper-id(field...)struct-option...)
The same as 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 struct/derived form is intended for use by macros that expand to struct .

Examples:
(define-syntax (fruit-structstx)
(syntax-case stx()
[(dsname. rest )
(with-syntax ([origstx])
#'(struct/derived origname(seedscolor). rest ))]))
> (fruit-structapple)
> (apple-seeds(apple12"red"))

12

> (fruit-structapple#:mutable)
> (set-apple-seeds!(apple12"red")8)
;this next line will cause an error due to a bad keyword
> (fruit-structapple#:bad-option)

eval:54:0: fruit-struct: unrecognized struct-specification

keyword

at: #:bad-option

in: (fruit-struct apple #:bad-option)

Added in version 7.5.0.16 of package base.

syntax

( define-struct/derived (id. rest-form)
id-maybe-super(field...)struct-option...)
Like struct/derived , 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. The define-struct/derived form is intended for use by macros that expand to define-struct .

Examples:
(define-syntax (define-xy-structstx)
(syntax-case stx()
[(dsname. rest )
(with-syntax ([origstx])
#'(define-struct/derived origname(xy). rest ))]))
> (define-xy-structposn)
> (posn-x(make-posn12))

1

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

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

struct-specification keyword

at: #:bad-option

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

Changed in version 7.5.0.16 of package base: Moved main description to struct/derived and replaced with differences.

top
up

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /