Search Top Index
HELP NEWANYSPARSE Jonathan Laventhol, 18 October 1984 Revised A.Sloman Oct 86 newanysparse(<integer|list:N>, <default value>) -> <sparse_array> newanysparse(<integer|list:N>, <procedure>, apply) -> <sparse_array> Constructs a <sparse_array> with N (or listlength(N)) dimensions, each cell initialised to <default value>, or using <procedure> to compute the entries -- Introduction ------------------------------------------------------- NEWANYSPARSE is a procedure which creates sparse arrays. For simple use, newsparse is recommended (see HELP *NEWSPARSE). Sparse arrays, like arrays, store data accessed by subscripts, but rather than having an vector holding the cells, as ordinary arrays do (see *ARRAYS), these use a tree of properties (see HELP *PROPERTIES) to hold the elements, and rather than requiring subscripts to be integers, as ordinary arrays do, sparse arrays allow any POPLOG items as subscripts. The use of properties makes it unnecessary to allocate space for cells which hold the default value. Sparse arrays are really procedures which access their own private property tree. Among the consequences of this are that fishing things out of the array is slower than for arrays. So speed is traded for space and generality. POP-11 sparse arrays can have 'active defaults' -- a procedure that is run to decide what the 'default value' of a cell is - i.e. what value to associate with a set of subscripts to which an explicit value has not been assigned. This can save an enormous amount of space. -- Making a Sparse Array ---------------------------------------------- The procedure newanysparse takes two arguments: newanysparse(<dimension-specifier>, <default>) -> <sparse_array> ; The <dimension-specifier> is either an integer giving the number of dimensions or a list giving size information for each dimension (See later section 'Controlling the Space') The <default> is the object which 'fills' the cells initially. This can be any POPLOG object. -- Examples ----------------------------------------------------------- Make a sparse array of 3 dimensions, every cell holding 0 newanysparse(3, 0) -> sa; Initially the default value is associated with everything: sa(1,2,3) => ** 0 Change the value of some of the cells: 6 -> sa(1,2,3); 720 -> sa(8,9,10); We can use sparse arrays for word lookup tables: vars dictionary; newanysparse(3, "something") -> dictionary; "bonjour" -> dictionary("french", "hello", "polite"); "ola" -> dictionary("spanish", "hello", "familiar"); -- Active Defaults ---------------------------------------------------- An especially useful feature of these arrays is to have the default result computed when needed, according to a rule. You might want an array of points containing a list of points they are connected to. The arrangement of your program might make it desirable that each point is intially connected to itself. Rather than take up storage for this, we can do it with a procedure such as this: define here(x, y, z) -> result; [[^x ^y ^z]] -> result enddefine; vars connected; newanysparse(3, here, apply) -> connected; In this array, each cell contains a list of the points it is directly connected to: connected(1,2,3) => ** [[1 2 3]] connected(8,9,10) => ** [[8 9 10]] You can then add the explicit connectivity for your problem: [8 9 10] :: connected(1,2,3) -> connected(1,2,3); connected(1,2,3) => ** [[8 9 10] [1 2 3]] Notice that the default procedure must have the same number of arguments as the number of dimensions of the array. (Also, this is the same procedure as one might use to initialise an ordinary array. See HELP *NEWANYARRAY) -- Controlling the Space ---------------------------------------------- In the dictionary example above, the arguments, left to right, are: language word manner We probably want only a few different languages in our dictionary, and there are only a few different manners for most languages. But there are many words we might want. You can specify approximately how big to make each dimension by makeing the sparse array like this: newanysparse([5 50 2], "dunno") -> dictionary; The list [5 50 2] says that you want three dimensions, the first of which is to have a table of size 5, the second dimension 50, and the third 2. These numbers affect only the size and speed of the resulting array. If you make them too small, your array will access cells slowly. If you make them large, it will take up more space. If you are interested in efficiency, you might like to know that it helps to put the smaller sized properties on the right-hand side of the argument list. -- Implemenation Details ---------------------------------------------- Giving 3 as the <dimension-specifier> is the same as [20 20 20]. The 'size' of each dimension is just the number to give to newproperty to make the hash-tables for the cells. The (inactive) default for the array is just the default value of the underlying properties. Arrays with active defaults have a unique, zero-length, string as this default. The pdprops of a sparse array procedure contain the default value. (See HELP *PDPROPS) The pdprops will be a list of length 3 for arrays with active defaults, length 2 otherwise. For those who want to know such things, the code for the three-dimensional sparse array made by newanysparse([20 10 5], 0) -> sparse_array; would be very similar to the code shown below. You may notice that the tree of properties is expanded only as necessary, but space is never reclaimed even if it were possible. vars myprop; newproperty([], 20, 0, true) -> myprop; define sparse_array(x, y, z); lvars prop x y z; myprop -> prop; if (prop(x) ->> prop) == 0 then return(0) elseif (prop(y) ->> prop) == 0 then return(0) else prop(z) endif enddefine; ;;; define updaterof sparse_array(newvalue, x, y, z); lvars nextprop prop x y z newvalue; myprop -> prop; prop -> nextprop; if (prop(x) ->> nextprop) == 0 then newproperty([], 10, 0, true) -> nextprop; nextprop -> prop(x); endif; nextprop -> prop; if (prop(y) ->> nextprop) == 0 then newproperty([], 5, 0, true) -> nextprop; nextprop -> prop(x); endif; newvalue -> nextprop(z) enddefine; ;;; cancel myprop; [sparse_array 0] -> pdprops(sparse_array); For implementation details SHOWLIB * NEWANYSPARSE See also: HELP * NEWSPARSE, * NEWPROPERTY, * NEWANYPROPERTY, * PROPERTIES REF * PROPS The last example in * NEWANYPROPERTY illustrates a different technique, employing a single property table. -----<Copyright University of Sussex 1986. All rights reserved.>-------