CML Reference Guide

Chapter 4.23:  Array Manipulation


Caucus version 4.3 adds a set of functions for manipulating "array objects".  These functions can be used, among many other possibilities, to add simple spreadsheet-like tables to Caucus.

Caucus arrays can have an arbitrary number of dimensions.  The number of dimensions is fixed when the array is created; but the size of each dimension may be changed dynamically.  In the descriptions below, di means a set of dimensions d1, d2, etc.  The dimensions appear in what is called "odometer ordering", meaning the rightmost dimension changes most rapidly. 

Thus, for example, a table "xyz" of 4 rows and 10 columns is a 2-dimensional array, represented by dimensions [4 10], and would be created by calling $array_create (xyz 4 10). When we look at such a table, we ordinarily "read" its cells proceeding from left to right, and then top to bottom.  This gives us our "odometer ordering" because we move fastest through the columns.

$array_create (name di)
Creates a permanent array called name with dimensions di.  Returns "1" if successful, "0" if the named array already exists.

$array_delete (name)
Permanently deletes array name.

$array (name di)
Evaluates to the value of cell di of array name.  If name is not already loaded into memory, loads the entire array into memory.  If the array or cell does not exist, evalues to nothing.  Array elements are numbered from 0 to the size of the dimension - 1.

$array_clear (name)
"Clears" (removes) array name from memory.  (This means that the next call to $array(name) will force it to be reloaded from disk.)  If many arrays are in use, clearing an array is useful to improve performance.

$array_set (name di string)
Sets the value of cell di of array name to string.  Like $array(), loads the array first if necessary.

$array_insert (name d n)
Inserts a new row or column in dimension d, just before index n.  For example, in a 2-dimensional array X, $array_insert (X 2 5) inserts a new, empty, column (dimension 2) just before the current column 5.  (Column 5 becomes column 6, 6 becomes 7, etc.)  $Array_insert (X 1 3) would insert a new row before row 3. Like $array(), loads the array first if necessary.

(Strictly speaking, $array_insert() inserts an array of one lower dimension at the index given.  So a vector gets a new cell inserted, a table gets a new row or column, a cube gets a new plane, etc.)

$array_remove (name d n)
Removes (deletes) a row or column at dimension d, index n.  Like $array(), loads the array first if necessary.

$array_size (name [d])
Evaluates to the size of dimension d.  If d is not specified, evaluates to the number of dimensions.  (Dimension numbers start at 1, unlike row, column, or cell indices.)  Like $array(), loads the array first if necessary.

$array_store (name)
Writes the current in-memory contents of array name to disk.  Note: you must call $array_store() in order to permanently save changes made by $array_set(), $array_insert(), or $array_remove()!

$array_eval (name di)
Evaluates to the contents of cell di of array name, including evaluating any CML functions or macros in the text of that cell, also including evaluating any of the "special array functions" that appear in the cell.  $Array_eval() automatically performs a recursive evaluation, so that (in particular) $cell() evaluations can refer to other $cell() evaluations.  (Recursion depth is limited to 20, to prevent infinite loops in case a cell accidentally refers to itself.) Like $array(), loads the array first if necessary.

Note:  the rest of the functions on this page are the "special array functions" mentioned in the description of $array_eval().  These functions look and act like regular CML functions, except that they also implicitly know which cell they are being evaluated on. 

In the descriptions of these functions, ci is a cell reference.  A cell reference may be either an absolute number such as "5", or a relative reference, such as "R2" or "R-1".  Relative references are, not surprisingly, relative to the current cell.  Thus R2 is the cell two cells higher in a dimension than the current cell; R-1 is one cell lower.  So, for example, in a two-dimensional array, a specific ci might be "5 R-1", meaning the cell in row 5 and the column one less than the current column.  These relative references are crucial for implementing spreadsheet-like capabilities.

$cell (ci [cj ...])
Evaluates to the value of cell ci, cj, etc., separated by blanks. 

$cells (ci cj)
Evaluates to the values of cells ci through cj.   Only one dimension may vary between i and j, e.g. in a table this can only evaluate to the cells in a row or column range.

Here's a particularly useful example that uses $cells() -- suppose array x, cell (6 3) (row 6, col 3) contains the text:

   $plus ($cells (0 R0  R-1 R0))
Then $array_eval (x 6 3) evaluates to the sum of all the values in the same column (3), from row 0 to the row before the current row (5).  This is the classic spreadsheet columnar sum operator.