An associative array or hash type
An Assoc_Type
object is like an array except that it is
indexed using strings and not integers. Unlike an Array_Type
object, the size of an associative array is not fixed, but grows as
objects are added to the array. Another difference is that ordinary
arrays represent ordered object; however, the ordering of the
elements of an Assoc_Type
object is unspecified.
An Assoc_Type
object whose elements are of some data-type
d
may be created using using
A = Assoc_Type[d];
For example,
A = Assoc_Type[Int_Type];
will create an associative array of integers. To create an
associative array capable of storing an arbitrary type, use the form
A = Assoc_Type[];
An optional parameter may be used to specify a default value for array elements. For example,
A = Assoc_Type[Int_Type, -1];
creates an integer-valued associative array with a default element
value of -1. Then A["foo"]
will return -1 if the key
"foo"
does not exist in the array. Default values are
available only if the type was specified when the associative array
was created.
The following functions may be used with associative arrays:
assoc_get_keys
assoc_get_values
assoc_key_exists
assoc_delete_key
The length
function may be used to obtain the number of
elements in the array.
The foreach
construct may be used with associative arrays via
on of the following forms:
foreach k,v (A) {...}
foreach k (A) using ("keys") { ... }
foreach v (A) using ("values") { ... }
foreach k,v (A) using ("keys", "values") { ... }
In all the above forms, the loop is over all elements of the array
such that v=A[k]
.
List_Type, Array_Type, Struct_Type
A list object
An object of type List_Type
represents a list, which is
defined as an ordered heterogeneous collection of objects.
A list may be created using, e.g.,
empty_list = {};
list_with_4_items = {[1:10], "three", 9, {1,2,3}};
Note that the last item of the list in the last example is also a
list. A List_Type object may be manipulated by the following
functions:
list_new
list_insert
list_append
list_delete
list_reverse
list_pop
A List_Type
object may be indexed using an array syntax with
the first item on the list given by an index of 0. The
length
function may be used to obtain the number of elements
in the list.
A copy of the list may be created using the @ operator, e.g.,
copy = @list
.
The foreach
statement may be used with a List_Type
objects to loop over its elements:
foreach elem (list) {....}
Array_Type, Assoc_Type, Struct_Type
A structure datatype
A Struct_Type
object with fields f1
, f2
,...,
fN
may be created using
s = struct { f1, f2, ..., fN };
The fields may be accessed via the "dot" operator, e.g.,
s.f1 = 3;
if (s12.f1 == 4) s.f1++;
By default, all fields will be initialized to NULL
.
A structure may also be created using the dereference operator (@):
s = @Struct_Type ("f1", "f2", ..., "fN");
s = @Struct_Type ( ["f1", "f2", ..., "fN"] );
Functions for manipulating structure fields include:
_push_struct_field_values
get_struct_field
get_struct_field_names
set_struct_field
set_struct_fields
The foreach
loop may be used to loop over elements of a linked
list. Suppose that first structure in the list is called
root
, and that the child
field is used to form the
chain. Then one may walk the list using:
foreach s (root) using ("child")
{
% s will take on successive values in the list
.
.
}
The loop will terminate when the last elements child
field is
NULL. If no ``linking'' field is specified, the field name will
default to next
.
User-defined data types are similar to the Struct_Type
. A
type, e.g., Vector_Type
may be created using:
typedef struct { x, y, z } Vector_Type;
Objects of this type may be created via the @ operator, e.g.,
v = @Vector_Type;
It is recommended that this be used in a function for creating such
types, e.g.,
define vector (x, y, z)
{
variable v = @Vector_Type;
v.x = x;
v.y = y;
v.z = z;
return v;
}
The action of the binary and unary operators may be defined for such
types. Consider the "+" operator. First define a function for
adding two Vector_Type
objects:
static define vector_add (v1, v2)
{
return vector (v1.x+v2.x, v1.y+v2.y, v1.z, v2.z);
}
Then use
__add_binary ("+", Vector_Type, &vector_add, Vector_Type, Vector_Type);
to indicate that the function is to be called whenever the "+"
binary operation between two Vector_Type
objects takes place,
e.g.,
V1 = vector (1, 2, 3);
V2 = vector (8, 9, 1);
V3 = V1 + V2;
will assigned the vector (9, 11, 4) to V3
. Similarly, the
"*"
operator between scalars and vectors may be defined using:
static define vector_scalar_mul (v, a)
{
return vector (a*v.x, a*v.y, a*v.z);
}
static define scalar_vector_mul (a, v)
{
return vector_scalar_mul (v, a);
}
__add_binary ("*", Vector_Type, &scalar_vector_mul, Any_Type, Vector_Type);
__add_binary ("*", Vector_Type, &vector_scalar_mul, Vector_Type, Any_Type);
Related functions include:
__add_unary
__add_string
__add_destroy
List_Type, Assoc_Type