Sometimes procedures need to operate on rather large data collections. If these are passed as value parameters, considerable resources of both time and memory may be consumed in copying the information from the main memory to the portion employed by the procedure. There are two possible ways around this problem.
One is to use a variable parameter, contrary to the usual recommendation for parameter passing. There is no copying, and the procedure's formal parameter becomes an alias to the actual parameter.
A second solution would be to pass a pointer to the data as a value parameter, rather than the data itself. For instance, if one had:
TYPE DataArray = ARRAY [1 ..100000] OF REAL; VAR theData : DataArray; PROCEDURE Mean1 (data : DataArray; lBound, uBound : CARDINAL) : REAL; (* find the mean of the array data from item #lBound to item #uBound *) VAR count, number : CARDINAL; total : REAL; BEGIN number := uBound - lBound + 1; IF number > 0 THEN total := 0.0; count := lBound; WHILE count <= uBound DO total := total + data [count]; INC (count); END; RETURN total / FLOAT (number) ELSE RETURN 0.0 END END Mean1;
and invoked this with
mean := Mean1 (theData, 1, 100000);
it might be useful to pass a value parameter pointer to the data array, rewriting things as:
TYPE DataPoint = POINTER TO DataArray; VAR dataP : DataPoint; PROCEDURE Mean2 (data : DataPoint; lBound, uBound : CARDINAL) : REAL;
with all as above except the line
total := total + data^ [count];
and invoke this by:
dataP := SYSTEM.ADR (theData); mean := Mean2 (dataP, 1, 100000);
In this manner, the procedure is referring to the original data, and only a pointer to that data needs to be passed rather than copying all of it to a value parameter.
The astute student will note at this juncture that the effect is exactly the same as if a variable parameter had been used in the first place, and wonder why one would go to all this trouble to imitate something that is already in the language. The answer is that in this case one would decidedly not go to the trouble. However, many, if not most systems actually implement variable parameters by passing a pointer. Although this action is transparent to the user, it is useful to know how it can be done (probably is done).
The example just concluded ought to make the same astute reader ask whether there are any other situations involving the moving of large quantities of data that can be avoided by the judicious use of pointers.
When one is sorting cardinals as will be done in the examples of chapter 13, the data movement involves rather small items. However, suppose that instead of sorting an array of cardinals, one is sorting arrays of rather large records. In such a situation, the movement of the data items can become so large a task that it overwhelms that of making comparisons, and any sorting method would quickly run into performance difficulties. In such cases, it may be best to keep an array of pointers to the data, make comparisons on the original data, and swap around only the pointers. This is especially true if one wants to sort the records according to different field values at different times (or even at the same time). To see the details of how this is achieved in a particular instance can be seen in section 13.6.2.