by Richard Russell, December 2009
In BBC BASIC for Windows you can perform operations on entire arrays, such as arithmetic operations and the dot product. For example:
a() = a() + b() + c() d() = e() * f() g() = h() . i() j() = 1, 2, 3, 4, 5
This is fine so long as the arrays you want to operate on are known in advance, but suppose you have a large number of arrays and you want to determine at run time which is acted upon.
Ideally what you might like to have is an array of arrays, then you could access the required array by means of an index, but BBC BASIC for Windows does not provide that facility. At first sight it would seem that a workaround would be to use an array of structures, each of which itself contains an array, but that won't work either because the entire array operations such as those listed above cannot be used with structure members.
However, all is not lost. Although you cannot use an array of arrays or an array of structures what you can use is an array of array-pointers. This allows you to achieve effectively what is required; performing an entire array operation on an array which is determined at run time by means of an index.
The main complication of this approach is that all operations on the individual arrays must be hived off into PROCedures, but this need not necessarily be too troublesome.
The code below illustrates such an approach. Firstly the array of array-pointers is declared to have the necessary number of elements:
number_of_arrays = 10 DIM array_pointer(number_of_arrays-1)
Next the individual arrays are DIMensioned; this must be done within a procedure (it is assumed here that all the arrays will be dimensioned identically, which will usually be the case):
FOR index% = 0 TO number_of_arrays-1 PROCdimarray(array_pointer(index%)) NEXT index% DEF PROCdimarray(RETURN array()) : DIM array(1,2) : ENDPROC
Here the procedure is shown 'inline' for convenience; in practice it would more likely be placed out of harm's way at the end of the program. Of course the dimensions (1,2) are simply illustrative; the arrays can be dimensioned however is required.
Having declared the arrays, one can perform operations on them. Suppose one wants to initialise each array with the same set of values:
DIM initial(1,2) initial() = 1, 2, 3, 4, 5, 6 FOR index% = 0 TO number_of_arrays-1 PROCinitarray(array_pointer(index%), initial()) NEXT DEF PROCinitarray(RETURN a(), i()) : a() = i() : ENDPROC
As before, the procedure is shown inline purely for convenience.
If one wished to initialise the arrays differently then that can be achieved in a similar way:
DIM initial(1,2) FOR index% = 0 TO number_of_arrays-1 initial() = 1, 2, 3, 4, 5, index% PROCinitarray(array_pointer(index%), initial()) NEXT
Of course there's no fundamental reason why the initial values need to be passed in another array initial(), they could (if there are relatively few elements) be passed as individual parameters to the procedure.
Now suppose one wants to do something a little more complicated, like adding two of the arrays together:
dst% = 3 src% = 6 PROCaddarray(array_pointer(dst%), array_pointer(src%)) DEF PROCaddarray(RETURN dst(), RETURN src()) : dst() += src() : ENDPROC
This adds the array with index src% to the array with index dst%.
If you want to perform a calculation on an array which returns a scalar value, a convenient way is to use a function rather than a procedure:
DIM result(number_of_arrays-1) FOR index% = 0 TO number_of_arrays-1 result(index%) = FNmod(array_pointer(index%)) NEXT DEF FNmod(RETURN array()) = MOD(array())
Hopefully you can now see a pattern emerging. Whenever you want to perform an operation on one or more of the arrays, you must put that operation in a procedure (or function, if appropriate) and call that procedure or function with one or more parameters which are pointers to the array(s). The procedure or function receives the array(s) as formal parameters and performs the necessary operations.