@c -----------------------------------------------------------------------------
@page
@node Structures, , Arrays, Data Types and Structures
@section Structures
@c -----------------------------------------------------------------------------

@menu
* Introduction to Structures::       
* Functions and Variables for Structures::       
@end menu

@c -----------------------------------------------------------------------------
@node Introduction to Structures, Functions and Variables for Structures, Structures, Structures
@subsection Introduction to Structures
@c -----------------------------------------------------------------------------

Maxima provides a simple data aggregate called a structure.
A structure is an expression in which arguments are identified by name (the field name)
and the expression as a whole is identified by its operator (the structure name).
A field value can be any expression.

A structure is defined by the @code{defstruct} function;
the global variable @code{structures} is the list of user-defined structures.
The function @code{new} creates instances of structures.
The @code{@@} operator refers to fields.
@code{kill(@var{S})} removes the structure definition @var{S},
and @code{kill(@var{x}@@ @var{a})} unbinds the field @var{a} of the structure instance @var{x}.

In the pretty-printing console display (with @mref{display2d} equal to @code{true}),
structure instances are displayed with the value of each field
represented as an equation, with the field name on the left-hand side
and the value on the right-hand side.
(The equation is only a display construct; only the value is actually stored.)
In 1-dimensional display (via @code{grind} or with @mref{display2d} equal to @code{false}),
structure instances are displayed without the field names.

There is no way to use a field name as a function name,
although a field value can be a lambda expression.
Nor can the values of fields be restricted to certain types; any field can be assigned any kind of expression.
There is no way to make some fields accessible or inaccessible in different contexts;
all fields are always visible.

@c -----------------------------------------------------------------------------
@node Functions and Variables for Structures,  , Introduction to Structures, Structures
@subsection Functions and Variables for Structures
@c -----------------------------------------------------------------------------

@c -----------------------------------------------------------------------------
@anchor{structures}
@defvr {Global variable} structures

@code{structures} is the list of user-defined structures defined by @code{defstruct}.

@opencatbox
@category{Structures}
@category{Global variables}
@closecatbox
@end defvr

@c -----------------------------------------------------------------------------
@anchor{defstruct}
@deffn  {Function} defstruct @
@fname{defstruct} (@var{S}(@var{a_1}, @dots{}, @var{a_n})) @
@fname{defstruct} (@var{S}(@var{a_1} = @var{v_1}, @dots{}, @var{a_n} = @var{v_n}))

Define a structure, which is a list of named fields @var{a_1}, @dots{},
@var{a_n} associated with a symbol @var{S}.
An instance of a structure is just an expression which has operator @var{S}
and exactly @code{n} arguments.
@code{new(@var{S})} creates a new instance of structure @var{S}.

An argument which is just a symbol @var{a} specifies the name of a field.
An argument which is an equation @code{@var{a} = @var{v}} specifies the field name @var{a}
and its default value @var{v}.
The default value can be any expression.

@code{defstruct} puts @var{S} on the list of user-defined structures, @code{structures}.

@code{kill(@var{S})} removes @var{S} from the list of user-defined structures,
and removes the structure definition.

Examples:

@c ===beg===
@c defstruct (foo (a, b, c));
@c structures;
@c new (foo);
@c defstruct (bar (v, w, x = 123, y = %pi));
@c structures;
@c new (bar);
@c kill (foo);
@c structures;
@c ===end===
@example
(%i1) defstruct (foo (a, b, c));
(%o1)                    [foo(a, b, c)]
(%i2) structures;
(%o2)                    [foo(a, b, c)]
(%i3) new (foo);
(%o3)                     foo(a, b, c)
(%i4) defstruct (bar (v, w, x = 123, y = %pi));
(%o4)             [bar(v, w, x = 123, y = %pi)]
(%i5) structures;
(%o5)      [foo(a, b, c), bar(v, w, x = 123, y = %pi)]
(%i6) new (bar);
(%o6)              bar(v, w, x = 123, y = %pi)
(%i7) kill (foo);
(%o7)                         done
(%i8) structures;
(%o8)             [bar(v, w, x = 123, y = %pi)]
@end example

@opencatbox
@category{Structures}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{new}
@deffn {Function} new @
@fname{new} (@var{S}) @
@fname{new} (@var{S} (@var{v_1}, @dots{}, @var{v_n}))

@code{new} creates new instances of structures.

@code{new(@var{S})} creates a new instance of structure @var{S}
in which each field is assigned its default value, if any,
or no value at all if no default was specified in the structure definition.

@code{new(@var{S}(@var{v_1}, ..., @var{v_n}))} creates a new instance of @var{S}
in which fields are assigned the values @var{v_1}, @dots{}, @var{v_n}.

Examples:

@c ===beg===
@c defstruct (foo (w, x = %e, y = 42, z));
@c new (foo);
@c new (foo (1, 2, 4, 8));
@c ===end===
@example
(%i1) defstruct (foo (w, x = %e, y = 42, z));
(%o1)              [foo(w, x = %e, y = 42, z)]
(%i2) new (foo);
(%o2)               foo(w, x = %e, y = 42, z)
(%i3) new (foo (1, 2, 4, 8));
(%o3)            foo(w = 1, x = 2, y = 4, z = 8)
@end example

@opencatbox
@category{Structures}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@deffn {Operator} @@

@code{@@} is the structure field access operator.
The expression @code{@var{x}@@ @var{a}} refers to the value of field @var{a} of the structure instance @var{x}.
The field name is not evaluated.

If the field @var{a} in @var{x} has not been assigned a value,
@code{@var{x}@@ @var{a}} evaluates to itself.

@code{kill(@var{x}@@ @var{a})} removes the value of field @var{a} in @var{x}.

Examples:

@c ===beg===
@c defstruct (foo (x, y, z));
@c u : new (foo (123, a - b, %pi));
@c u@z;
@c u@z : %e;
@c u;
@c kill (u@z);
@c u;
@c u@z;
@c ===end===
@example
(%i1) defstruct (foo (x, y, z));
(%o1)                    [foo(x, y, z)]
(%i2) u : new (foo (123, a - b, %pi));
(%o2)           foo(x = 123, y = a - b, z = %pi)
(%i3) u@@z;
(%o3)                          %pi
(%i4) u@@z : %e;
(%o4)                          %e
(%i5) u;
(%o5)            foo(x = 123, y = a - b, z = %e)
(%i6) kill (u@@z);
(%o6)                         done
(%i7) u;
(%o7)              foo(x = 123, y = a - b, z)
(%i8) u@@z;
(%o8)                          u@@z
@end example

The field name is not evaluated.

@c ===beg===
@c defstruct (bar (g, h));
@c x : new (bar);
@c x@h : 42;
@c h : 123;
@c x@h;
@c x@h : 19;
@c x;
@c h;
@c ===end===
@example
(%i1) defstruct (bar (g, h));
(%o1)                      [bar(g, h)]
(%i2) x : new (bar);
(%o2)                       bar(g, h)
(%i3) x@@h : 42;
(%o3)                          42
(%i4) h : 123;
(%o4)                          123
(%i5) x@@h;
(%o5)                          42
(%i6) x@@h : 19;
(%o6)                          19
(%i7) x;
(%o7)                    bar(g, h = 19)
(%i8) h;
(%o8)                          123
@end example

@opencatbox
@category{Structures}
@category{Operators}
@closecatbox
@end deffn

