10. Arrays

10.1 What Arrays Are
An array is a Lisp object that consists of a of cells, each of which may contain a Lisp object. The individual cells are selected by numerical subscripts .

There are many types of arrays. Some types of arrays can hold Lisp objects of any type; the other types of arrays can only hold fixnums. The array types are known by a set of symbols symbols whose names begin with "art- " (for ARray Type).

array-types Variable
The value of array-types is a list of all of the array type symbols such as art-q , art-4b , art-string and so on.
array-types array-type-code
An array of the array type symbols, indexed by their internal numeric codes.
array-elements-per-q Variable
array-elements-per-q is an association list (see this link) which associates each array type symbol with the number of array elements stored in one word, for an array of that type. If the value is negative, it is instead the number of words per array element, for arrays whose elements are more than one word long.
array-elements-per-q array-type-code
This is an array, indexed by the internal codes of the array types, containing the number of array elements stored in one word, for an array of that type. If the value is negative, it is instead the number of words per array element, for arrays whose elements are more than one word long.
array-bits-per-element Variable
The value of array-bits-per-element is an association list (see this link) which associates each array type symbol with the number of bits of unsigned number it can hold, or nil if it can hold Lisp objects. This can be used to tell whether an array can hold Lisp objects or not.
array-bits-per-element array-type-code
This is an array, indexed by the internal codes of the array types, containing the number of bits per cell for unsigned numeric arrays, and nil for full-Lisp-object-containing array.
array-element-size array
Given an array, returns the number of bits that fit in an element of that array. For non-numeric arrays, the result is 24., assuming you will be storing unsigned fixnums in the array.
The most commonly used type is called art-q . An art-q array simply holds Lisp objects of any type. Similar to the art-q type is the art-q-list . Like the art-q , its elements may be any Lisp object. The difference is that the art-q-list array "doubles" as a list; the function g-l-p will take an art-q-list array and return a list object whose elements are those of the array, and whose actual substance is that of the array. If you rplaca elements of the list, the corresponding element of the array will change, and if you store into the array, the corresponding element of the list will change the same way. There is a set of types called art-1b, art-2b, art-4b, art-8b and art-16b ; these names are short for "1 bit", "2 bits", and so on. Each element of an art-1b array is a fixnum, and only one bit (the least significant) is remembered in the array; all of the others are discarded. Similarly, in an art-2b array, only the two least significant bits are remembered. So if you store a 5 into an art-2b array, for example, and look at it later, you will find a 1 rather than a 5. These arrays are used when it is known beforehand that the fixnums which will be stored are non-negative and limited in size to a certain number of bits. Their advantage over the art-q array is that they occupy less storage, because more than one element of the array is kept in a single machine word. (For example, 32 elements (decimal) of an art-1b array or 2 elements of an art-16b array will fit into one word). Character strings are implemented by the art-string array type. This type acts similarly to the art-8b ; its elements must be fixnums, of which only the least significant eight bits are stored. However, many important system functions, including read , print , and eval , treat art-string arrays very differently from the other kinds of arrays. These arrays are usually called string s, and an entire chapter of this manual deals with functions which manipulate them. There are three types of arrays which exist only for the purposes of stacks ; these types are called art-stack-head, art-special-pdl and art-reg-pdl . Their elements may be any Lisp object; their use is explained in the section on stacks (see this link).

The art-float array type is a special purpose type whose elements are flonums. When storing into such an array the value will be converted to a flonum. The advantage of storing flonums in an art-float array rather than an art-q array is that the numbers in an art-float array are not true Lisp objects. Instead the array remembers the numerical value, and when it is aref 'ed creates a Lisp object (a flonum) to hold the value. Because the system does special storage management for bignums and flonums that are intermediate results the use of art-float arrays can save a lot of work for the garbage-collector and hence greatly increase performance. An intermediate result is a Lisp object passed as an argument, stored in a local variable, or returned as the value of a function, but not stored into a global variable, an array, or list structure. art-float arrays also provide a locality of reference advantage over art-q arrays containing flonums.

10.2 How Arrays Work
The dimensionality of an array (or, the number of dimensions which the array has) is the number of subscripts used to refer to one of the elements of the array. The dimensionality may be any integer from one to seven, inclusively. The lowest value for any subscript is zero; the highest value is a property of the array. Each dimension has a size, which is the lowest number which is too great to be used as a subscript. For example, in a one dimensional array of five elements, the size of the one and only dimension is five, and the acceptable values of the subscript are zero, one, two, three, and four. The most basic primitive functions for handling arrays are: make-array , which is used for the creation of arrays, aref , which is used for examining the contents of arrays, and aset , which is used for storing into arrays. An array is a regular Lisp object, and it is common for an array to be the binding of a symbol, or the car or cdr of a cons, or, in fact, an element of an array. Another way of handling arrays, inherited from Maclisp, is to treat them as functions. In this case each array has a name, which is a symbol whose function definition is the array. The Lisp machine supports this style by allowing an array to be applied to arguments, as if it were a function. The arguments are treated as subscripts and the array is referenced appropriately. The store special form (see LINK:(store-fun)) is also supported. This form of array referencing is considered to be obsolete, and should not be used in new programs. Here are some issues of Maclisp compatibility: Fixnum arrays do not exist (however, see the Lisp machine's small-positive-number arrays). Flonum arrays exist but you do not use them in the same way; no declarations are required or allowed. "Un-garbage-collected" arrays do not exist. 'c yet??? --weak links Readtables and obarrays are represented as arrays, but unlike Maclisp special array types are not used. See the descriptions of read (LINK:(read-fun)) and intern (LINK:(intern-fun)) for information about readtables and obarrays (packages). There are no "dead" arrays, nor are Multics "external" arrays provided. The arraycall function is not used (see aref , LINK:(aref-fun).) Subscripts are always checked for validity, regardless of the value of *rset and whether the code is compiled or not. However, in a multi-dimensional array, an error is only caused if the subscripts would have resulted in a reference to storage outside of the array; so if you have a 2 by 7 array and refer to an element with subscripts 3 and 1, no error will be caused despite the fact that the reference is invalid; but if you refer to element 1 by 100, an error will be caused. In other words, any subscript error which is not detected will only refer to somewhere else in your array, and not to any other part of storage. Currently multi-dimensional arrays are stored in column-major order rather than row-major order as in Maclisp. This has an effect on paging performance when using large arrays. Row-major order means that successive memory locations differ in the last subscript, while column-major order means that successive memory locations differ in the first subscript. loadarrays and dumparrays are not provided. However, arrays can be put into "QFASL" files; see the section on fasloading (LINK:(fasload-fun)).
10.3 Extra Features of Arrays

Any array may have an array leader . An array leader is like a one-dimensional art-q array which is attached to the main array. So an array which has a leader acts like two arrays joined together. It can be stored in and examined by a special set of functions which are analogous to those used for the main array: array-leader and store-array-leader . The leader is always one-dimensional, and always can hold any kind of Lisp object, regardless of the type or dimensionality of the array. By convention, the zeroth element of the array leader of an array is used to hold the number of elements in the array that are "active" in some sense. When the zeroth element is used this way, it is called a fill pointer .

Specifically, if a string (an array of type art-string ) has seven elements, but it has a fill pointer of five, then only elements zero through four of the string are considered to be "active"; the string's printed representation will be five characters long, string-searching functions will stop after the fifth element, etc. The second element is also used in conjunction with the "named structure" feature; see this link.

The following explanation of displaced arrays is probably not of interest to a beginner; the section may be passed over without losing the continuity of the manual. Normally, an array consists of a small amount of header information, followed by the contents of the array. However, sometimes it is desirable to have the header information removed from the actual contents. One such occasion is when the contents of the array must be located in a special part of the Lisp Machine's address space, such as the area used for the control of input/output devices. Displaced arrays are also used to reference certain special system tables, which are at fixed addresses so the microcode can access them easily. If you give make-array a fixnum as its fourth argument, it will create a displaced array refering to that location of virtual memory. References to elements of the displaced array will access that part of storage, and return the contents; the regular aref and aset functions are used. If the array is one whose elements are Lisp objects, caution should be used: if the region of address space does not contain typed Lisp objects, the integrity of the storage system could be damaged by the garbage collector. If the array is one whose elements are bytes (such as an art-4b type), then there is no problem. It is important to know, in this case, that the elements of such arrays are allocated from the right to the left within the 32-bit words. See the description of internal array formats on LINK:(array-format).

It is also possible to have an array whose contents, instead of being located at a fixed place in virtual memory, are defined to be those of another array. Such an array is called an indirect array , and is created by giving make-array an array as its fourth argument. The effects of this are simple if both arrays have the same type; the two arrays share all elements. An object stored in a certain element of one can be retrieved from the corresponding element of the other. This, by itself, is not very useful. However, if the arrays have different dimensionality, the manner of accessing the elements differs. Thus, by creating a one-dimensional array of nine elements which was indirected to a second, two-dimensional array of three elements by three, then the elements could be accessed in either a one-dimensional or a two-dimensional manner. Even more complex effects can be produced if the new array is of a different type than the old array; see the description of internal array formats on LINK:(array-format).

It is also possible to create a one-dimensional indirect array in such a way that when an attempt is made to reference it or store into it, a constant number is added to the subscript given. This number is called the index-offset , and is specified at the time the indirect array is created, by giving a fixnum to make-array as its sixth argument. The nsubstring function (see LINK:(nsubstring-fun)) creates such arrays. 'findex "nsubstring"

10.4 Basic Array Functions
make-array area type dims &optional displaced-p leader index-offset named-structure
This creates and returns an array, according to various specifications. The area parameter specifies the area in which to allocate the array's storage; if you are not concerned with areas, simply use nil which as always means the default area. type should be a symbolic name of an array type; the most common of these is art-q . The elements of the array are initialized according to the type: if the array is of a type whose elements may only be fixnums or flonums, then every element of the array will initially be 0 ; otherwise, every element will initially be nil . See the description of array types on this link.

dims should be a list of fixnums which are the dimensions of the array; the length of the list will be the dimensionality of the array. For convenience, if the dimensionality should be one, the single dimension may be provided as a fixnum rather than a list of one fixnum.

Examples:
(setq a (make-array nil 'art-q 5))       ; Create a one-d array 
					 ;of 5 elements. 

(setq b (make-array nil 'art-4b '(3 4))) ; Create a four-bit two-d 
					 ;array, 3 by 4. 
If displaced-p is not nil , then the array will be a displaced array. displaced-p may either be a fixnum, to create a regular displaced array which refers to a certain section of virtual address space, or an array, to create an indirect array (see this link).

If leader is not nil , then the array will be given a leader. If leader is a fixnum, the array's leader will be leader elements long, and its elements will be initialized to nil . Leader may also be a list, in which case the length of the leader is equal to that of the list, and the elements are initialized to the elements of the list, in reverse order (i.e., the car of the list is stored in the highest-subscripted location in the leader). If index-offset is present, displaced-p should be an array, and index-offset should be a fixnum; it is made to be the index-offset of the created indirect array. (See this link.)

If named-structure is not nil , it is a symbol to be stored in the named-structure cell element of the array. The array created will be a named structure (see this link.)

Examples:
(make-array nil 'art-q 5 nil 3)   ;;leader 3 elements long. 
(setq a (make-array nil 'art-1b 100 nil '(t nil)))
(array-leader a 0) => nil
(array-leader a 1) => t

make-array returns the newly-created array, and also returns, as a second value, the number of words allocated from area in the process of creating the array.

array-displaced-p array
array may be any kind of array. This predicate returns t if array is any kind of displaced array (including indirect arrays). Otherwise it returns nil .
array-indirect-p array
array may be any kind of array. This predicate returns t if array is an indirect array. Otherwise it returns nil .
array-indexed-p array
array may be any kind of array. This predicate returns t if array is an indirect array with an index-offset. Otherwise it returns nil .
adjust-array-size array new-size
array should be a one-dimensional array. Its size is changed to be new-size . If this results in making array smaller, then the extra elements are lost; if array is made bigger, the new elements are initialized in the same fashion as make-array (see LINK:(make-array-fun)): either to nil or 0 . [Currently there is a bug which causes initialization to zero not to work.]
Example:
(setq a (make-array nil 'art-q 5))
(aset 'foo a 4)
(aref a 4) => foo
(adjust-array-size a 2)
(aref a 4) => ERROR
If the size of the array is being increased, adjust-array-size must allocate a new array somewhere; it then alters array so that references to it will be made to the new array instead, by means of an "invisible pointer". adjust-array-size will return this new array if it creates one, and otherwise it will return array . Be careful about using the returned result of adjust-array-size , because you may end up holding two arrays which are not the same (i.e., not eq ) which share the same contents.
return-array array
Return array to free storage. If it is displaced, this returns the pointer, not the data pointed to. Currently does nothing if the array is not at the end of its area. This will eventually be renamed to reclaim , when it works for other objects than arrays.
aref array &rest subscripts
Returns the element of array selected by the subscripts . The subscripts must be fixnums and their number must match the dimensionality of array .
ar-1 array i
array should be a one-dimensional array, and i should be a fixnum. This returns the i 'th element of array .
ar-2 array i j
array should be a two-dimensional array, and i and j should be fixnums. This returns the i by j 'th element of array .
ar-3 array i j k
array should be a three-dimensional array, and i , j , and k should be fixnums. This returns the i by j by k 'th element of array .
aset x array &rest subscripts
Stores x into the element of array selected by the subscripts . The subscripts must be fixnums and their number must match the dimensionality of array . The returned value is x .
as-1 x array i
array should be a one-dimensional array, and i should be a fixnum. x may be any object. x is stored in the i 'th element of array . as-1 returns x .
as-2 x array i j
array should be a two-dimensional array, and i and j should be fixnums. x may be any object. x is stored in the i by j 'th element of array . as-2 returns x .
as-3 x array i j k
array should be a three-dimensional array, and i , j , and k should be fixnums. x may be any object. x is stored in the i by j by k 'th element of array . as-3 returns x .
aloc array &rest subscripts
Returns a locative pointer to the element-cell of array selected by the subscripts . The subscripts must be fixnums and their number must match the dimensionality of array .
ap-1 array i
array should be a one-dimensional array whose elements contain Lisp objects, and i should be a fixnum. This returns a locative pointer to the i 'th element of array . See the explanation of locatives, this link.
ap-2 array i j
array should be a two-dimensional array whose elements contain Lisp objects, and i and j should be fixnums. This returns a locative pointer to the i by j 'th element of array . See the explanation of locatives, this link.
ap-3 array i j k
array should be a three-dimensional array whose elements contain Lisp objects, and i , j , and k should be fixnums. This returns a locative pointer to the i by j by k 'th element of array . See the explanation of locatives, this link.
The compiler turns aref into ar-1 , ar-2 , etc. according to the number of subscripts specified, turns aset into as-1 , as-2 , etc., and turns aloc into ap-1 , ap-2 , etc. For arrays with more than 3 dimensions the compiler uses the slightly less efficient form since the special routines only exist for 1, 2, and 3 dimensions. There is no reason for any program to call ar-1 , as-1 , ar-2 , etc. explicitly; they are documented because there used to be such a reason, and many existing programs use these functions. New programs should use aref , aset , and aloc .
arraycall ignored array &rest subscripts
(arraycall nil array sub1 sub2...) is the same as (aref array sub1 sub2...) . It exists for Maclisp compatibility.
get-list-pointer-into-array array-ref
The argument array-ref is ignored, but should be a reference to an art-q-list array by applying the array to subscripts (rather than by aref ). This returns a list object which is a portion of the "list" of the array, beginning with the last element of the array which has been referenced.
g-l-p array
array should be an art-q-list array. This returns a list which shares the storage of array . The art-q-list type exists so that g-l-p can be used.
Example:
(setq a (make-array nil 'art-q-list 4))
(aref a 0) => nil
(setq b (g-l-p a)) => (nil nil nil nil)
(rplaca b t)
b => (t nil nil nil)
(aref a 0) => t
(aset 30 a 2)
b => (t nil 30 nil)
get-locative-pointer-into-array array-ref
get-locative-pointer-into-array is similar to get-list-pointer-into-array , except that it returns a locative, and doesn't require the array to be art-q-list .
arraydims array
array may be any array; it also may be a symbol whose function cell contains an array, for Maclisp compatibility (see LINK:(maclisp-array)). It returns a list whose first element is the symbolic name of the type of array , and whose remaining elements are its dimensions.
Example:
(setq a (make-array nil 'art-q '(3 5)))
(arraydims a) => (art-q 3 5)
array-dimensions array
array-dimensions returns a list whose elements are the dimensions of array .
Example:
(setq a (make-array nil 'art-q '(3 5)))
(array-dimensions a) => (3 5)
Note: the list returned by (array-dimensions x) is equal to the cdr of the list returned by (arraydims x) .
array-in-bounds-p array &rest subscripts
This function checks whether the subscripts are all legal subscripts for array , and returns t if they are; otherwise it returns nil .
array-length array
array may be any array. This returns the total number of elements in array . For a one-dimensional array, this is one greater than the maximum allowable subscript. (But if fill pointers are being used, you may want to use array-active-length (see LINK:(array-active-length-fun))).
Example:
(array-length (make-array nil 'art-q 3)) => 3
(array-length (make-array nil 'art-q '(3 5)))
		=> 17  ;octal, which is 15. decimal 
array-/#-dims array
Returns the dimensionality of array . Note that the name of the function includes a "#", which must be slashified if you want to be able to compile your program with the compiler running in Maclisp.
Example:
(array-/#-dims (make-array nil 'art-q '(3 5))) => 2
array-dimension-n n array
array may be any kind of array, and n should be a fixnum. If n is between 1 and the dimensionality of array , this returns the n 'th dimension of array . If n is 0 , it returns the length of the leader of array ; if array has no leader it returns nil . If n is any other value, it returns nil .
Examples:
(setq a (make-array nil 'art-q '(3 5) nil 7))
(array-dimension-n 1 a) => 3
(array-dimension-n 2 a) => 5
(array-dimension-n 3 a) => nil
(array-dimension-n 0 a) => 7
array-type array
Returns the symbolic type of array .
Example:
(setq a (make-array nil 'art-q '(3 5)))
(array-type a) => art-q
fillarray array x
Note: for the present, all arrays concerned must be one-dimensional. array may be any type of array, or, for Maclisp compatibility, a symbol whose function cell contains an array. There are two forms of this function, depending on the type of x . If x is a list, then fillarray fills up array with the elements of list . If x is too short to fill up all of array , then the last element of x is used to fill the remaining elements of array . If x is too long, the extra elements are ignored. If x is an array (or, for Maclisp compatibility, a symbol whose function cell contains an array), then the elements of array are filled up from the elements of x . If x is too small, then the extra elements of array are not affected. fillarray returns array .
listarray array &optional limit
Note: for the present, all arrays concerned must be one-dimensional. array may be any type of array, or, for Maclisp compatibility, a symbol whose function cell contains an array. listarray creates and returns a list whose elements are those of array . If limit is present, it should be a fixnum, and only the first limit (if there are more than that many) elements of array are used, and so the maximum length of the returned list is limit .
copy-array-contents from to
from and to must be arrays. The contents of from is copied into the contents of to , element by element. Presently the first subscript varies fastest in multi-dimensional arrays (opposite from Maclisp). If to is shorter than from , the excess is ignored. If from is shorter than to , the rest of to is filled with nil if it is a q-type array or 0 if it is a numeric array or 200 if it is a string. t is always returned. Note that even if from or to has a leader, the whole array is used; the convention with leader element 0 being the "active" length of the array is not used by this function.
copy-array-portion from-array from-start from-end to-array to-start to-end
The portion of the array from-array with indices greater than or equal to from-start and less than from-end is copied into the portion of the array to-array with indices greater than or equal to to-start and less than to-end , element by element. If there are more elements in to-array , the extra elements are filled as in copy-array-contents . t is always returned.
10.5 Array Leaders

Array leaders were introduced at the beginning of the chapter. This section presents various functions which operate on array leaders.

array-has-leader-p array
array may be any array. This predicate returns t if array has a leader; otherwise it returns nil .
array-leader-length array
array may be any array. This returns the length of array 's leader if it has one, or nil if it does not.
array-leader array i
array should be an array with a leader, and i should be a fixnum. This returns the i 'th element of array 's leader. This is analogous to aref .
store-array-leader x array i
array should be an array with a leader, and i should be a fixnum. x may be any object. x is stored in the i 'th element of array 's leader. store-array-leader returns x . This is analogous to aset .
ap-leader array i
array should be an array with a leader, and i should be a fixnum. This returns a locative pointer to the i 'th element of array 's leader. See the explanation of locatives, this link. This is analogous to aloc .
array-active-length array
If array does not have a fill pointer, then this returns whatever (array-length array) would have. If array does have a fill pointer, array-active-length returns it. See the general explanation of the use of fill pointers, which is at the beginning of this section.
array-push array x
array must be a one-dimensional array which has a fill pointer, and x may be any object. array-push attempts to store x in the element of the array designated by the fill pointer, and increase the fill pointer by one. If the fill pointer does not designate an element of the array (specifically, when it gets too big), it is unaffected and array-push returns nil ; otherwise, the two actions (storing and incrementing) happen uninterruptibly, and array-push returns the former value of the fill pointer (one less than the one it leaves in the array). If the array is of type art-q-list , an operation similar to nconc has taken place, in that the element has been added to the list by changing the cdr of the formerly last element.
array-push-extend array x
array-push-extend is just like array-push except that if the fill pointer gets too large, the array is grown to fit the new element; i.e. it never "fails" the way array-push does, and so never returns nil .
array-pop array
array must be a one-dimensional array which has a fill pointer. The fill pointer is decreased by one, and the array element designated by the new value of the fill pointer is returned. If the new value does not designate any element of the array (specifically, if it has reached zero), an error is caused. The two operations (decrementing and array referencing) happen uninterruptibly. If the array is of type art-q-list , an operation similar to nbutlast has taken place.
list-array-leader array &optional limit
array may be any type of array, or, for Maclisp compatibility, a symbol whose function cell contains an array. list-array-leader creates and returns a list whose elements are those of array 's leader. If limit is present, it should be a fixnum, and only the first limit (if there are more than that many) elements of array 's leader are used, and so the maximum length of the returned list is limit . If array has no leader, nil is returned.
copy-array-contents-and-leader from to
This is just like copy-array-contents (see LINK:(copy-array-contents-fun)), but the leaders of from and to are also copied.
10.6 Maclisp Array Compatibility
Note: the functions in this section should not be used in new programs. In Maclisp, arrays are usually kept on the array property of symbols, and the symbols are used instead of the arrays. In order to provide some degree of compatibility for this manner of using arrays, the array , *array , and store functions are provided, and when arrays are applied to arguments, the arguments are treated as subscripts and apply returns the corresponding element of the array. However, the *rearray , loadarrays , and dumparrays functions are not provided. Also, flonum , readtable , and obarray type arrays are not supported.
array "e symbol type &eval &rest dims
This creates an art-q type array in default-array-area with the given dimensions. (That is, dims is given to make-array as its third argument.) type is ignored. If symbol is nil , the array is returned; otherwise, the array is put in the function cell of symbol , and symbol is returned.
*array symbol type &rest dims
This is just like array , except that all of the arguments are evaluated.
store "e array-ref x
x may be any object; array-ref should be a form which references an array by calling it as a function (aref forms are not acceptable). First x is evaluated, then array-ref is evaluated, and then the value of x is stored into the array cell which was referenced by the evaluation of array-ref .
xstore x array-ref
This is just like store , but it is not a special form; this is because the arguments are in the other order. This function only exists for the compiler to compile the store special form, and should never be used by programs.