Next: , Up: syslib structs safe   [Index]


12.14.1.1 Defining structure types

Syntax: define-struct ?type-name (?field …)
Syntax: define-struct ?type-name (?field …) (nongenerative ?uid)
Syntax: define-struct (?type-name ?constructor ?predicate) (?field …)
Syntax: define-struct (?type-name ?constructor ?predicate) (?field …) (nongenerative ?uid)
Auxiliary Syntax: nongenerative

Define a new struct type. This macro is embedded in the expander.

?type-name must be a symbol representing the name of the structure; it is used to build names for the constructor, predicate, field accessors and mutators. When ?constructor is used: it must be an identifier representing the name of the constructor. When ?predicate is used: it must be an identifier representing the name of the predicate.

The ?field values must be either symbols representing the names of the fields or brace forms representing the name and type of fields:

(brace ?field-name ?tag)

they are used to build names for the accessors and mutators.

When the nongenerative clause is used: ?uid must be a symbol uniquely identifying the struct type. Multiple definitions of struct type using the same ?uid must have the same type name and field names, and represent the same type definition. See make-struct-type for more details.

The following definition:

(define-struct color
  (red green blue))

expands to the definition of the following syntactic bindings:

color

A syntactic identifier representing the type name. When the tagged language is enabled, we can use this identifier to tag a variable syntactic binding:

(define {O color}
  (make-color 1 2 3))

(O red)         ⇒ 1
(O green)       ⇒ 2
(O blue)        ⇒ 3

We can use the identifier as argument for the is-a? syntax:

(is-a? (make-color 1 2 3) color)        ⇒ #t
(is-a? "ciao" color)                    ⇒ #f

When the identifier is used in macro keyword position with the syntax:

(?type-name (?expr ...))

the form is expanded to the application of the constructor to the results of evaluating the ?expr arguments:

(color (1 2 3)) ⇒ #["color" red=1 green=2 blue=3]
make-color red green blue

A structure constructor accepting as much arguments as there are fields. The constructor makes use of the $struct low level operation.

color? obj

A predicate to distinguish between references to color structures and other values. This predicate makes use of the $struct/rtd? low level operation.

color-red stru
color-green stru
color-blue stru

Accessor functions for the fields of the structure. These accessors make use of the $struct/rtd? low level operation to validate the argument and if successful they use $struct-ref to extract the value; if the argument is of invalid type: an assertion violation is raised.

set-color-red! stru red
set-color-green! stru green
set-color-blue! stru blue

Mutator functions for the fields of the structure. These mutators make use of the $struct/rtd? low level operation to validate the argument stru and if successful they use $struct-set! to set the value; if the argument stru is of invalid type: an assertion violation is raised.

$color-red stru
$color-green stru
$color-blue stru

Unsafe accessor syntaxes for the fields of the structure. These accessors do not validate the arguments and expand directly to a use of $struct-ref to extract the value; if the argument is invalid: the behaviour is undefined.

$set-color-red! stru red
$set-color-green! stru green
$set-color-blue! stru blue

Unsafe mutator syntaxes for the fields of the structure. These mutators do not validate the arguments and expand directly to a use of $struct-set! to set the value; if the argument stru is invalid: the behaviour is undefined.

Function: make-struct-type type-name fields
Function: make-struct-type type-name fields uid

Build and return a new struct–type descriptor. type-name must be a string representing the type name. fields must be a list of symbols representing the field names.

The optional uid argument must be a symbol uniquely identifying this type; when not supplied, a symbol is automatically generated. The value field of the symbol object uid is set to the newly created RTD; if uid already has a symbol value: such value must be a struct descriptor equal to the newly created RTD.

The use of a uid allows us to define a unique struct type in different libraries without sharing the definition by importing syntactic bindings. For example, we can define a struct type in a library and import the definition in other libraries:

(library (one)
  (export
    make-color color?
    color-red color-green color-blue)
  (import (vicare))
  (define-struct color
    (red green blue)))

(library (two)
  (export C)
  (import (vicare) (one))
  (define C (make-color 1 2 3)))

(library (three)
  (export)
  (import (vicare) (one) (two))
  (display (color-red C)))

but, by specifying a uid, we can also do:

(library (two)
  (export C)
  (import (vicare))
  (define-struct color
    (red green blue)
    (nongenerative the-color))
  (define C
    (make-color 1 2 3)))

(library (three)
  (export)
  (import (vicare))
  (define-struct color
    (red green blue)
    (nongenerative the-color))
  (display (color-red C)))

and everything will work as before.


Next: , Up: syslib structs safe   [Index]