Parameter Passing in Pascal
Mordechai Ben-Ari Department of Science Teaching
Weizmann Institute of Science Rehovot 76100 Israel ntbenari@wis.weizmann.ac.il
Abstract
This paper claims that reference parameters as such should not be taught in introductory courses on programming that use Pascal or C++. Rather, formal ref- erence parameters should be taught as renamings of the actual parameters. Fur- thermore, the choice between copy and reference parameters should be based on intended use, not on implementation. We show that reference parameters are not as efficient as is naively believed, so there is no impediment to the proposed criterion.
1 Introduction
My group develops a two-year course called “Fundamentals of Computer Science” for high-school students (10th and 11th grade). Teachers of the course uniformly report that many students have difficultly forming a mental model of a computer; for example, students often struggle with the semantics of the read statement, because it is not clear
“who” is reading “what” from “where”!
Since pointers are not taught within this course, a question we had to deal with was how to teach reference parameters without explicitly expanding the mental model of the computer to include variables containing machine addresses. The question is important since modern introductory computer science courses emphasize algorithms, not machines; one ought to be able to develop and implement a sort algorithm without understanding the underlying machine.
This article reports on techniques developed to teach parameters that employ in- tended use rather than implementation of the parameter passing mechanism to guide the presentation. The techniques will be especially useful to teachers of non-majors who cannot be expected to develop a full model of a computer in the short time they are exposed to the subject.
The discussion is given for the Pascal language; it is directly applicable to C++
which uses the same two parameter passing modes. C, of course, requires the early introduction of pointers, and this is a major reason why the language is difficult to teach.
Ada’s parameter passing modes are specified in terms of use rather than implementation and were the inspiration for this work. Languages based on reference semantics (Eiffel,
Smalltalk, Java) do not need reference parameters since any actual parameter can be modified and any object returned.
The paper is organized as follows. We review the concepts or value and reference parameters in Section 2, and then in Section 3 discuss parameter modes in Ada. Sec- tion 4 shows how to transfer the Ada concepts to Pascal and Section 5 discusses the immediate objection that is always raised: the alleged inefficiency of value parameters.
In Section 6 we present our method for teaching parameters as renamings.
2 Value and reference parameters
Pascal has two modes for passing parameters to a procedure or function: value and reference. The former is the default and the latter is indicated by the use of the keyword var in front of the formal parameter. In value mode the actual parameter can be an expression and the formal parameter contains a copy of the value of the expression.
Any assignment to the formal parameter does not affect the actual parameter, even if the actual parameter is a variable. In reference mode the actual parameter must be a variable and the formal parameter contains a pointer to that variable. Assignment to the formal parameter is an assignment to the actual parameter.
Value parameters are, of course, easy to teach because they are equivalent to initial- ized local variables. However, reference parameters are correctly explained in terms of pointers and address; for example [2], p. 241:
The compiler stores the memory address of the actual parameter that cor- responds to each variable parameter in the procedure data area.
This is an advanced concept best deferred as long as possible. The problem with the definition of Pascal is that it is given in terms of implementation, while most program- mers (and certainly beginning students) need only be aware of the rules concerning the intended use of the parameters.
3 Parameter modes in Ada
Parameter passing in Ada is defined by intended use and is thus easier to teach than the Pascal definition. Consider the following procedure declarations:
procedure Quadratic(
A, B, C: in Float; Root1, Root2: out Float);
procedure Sort(V: in out Vector);
Parameters of mode in can only be read, parameters of mode out can only be written, and parameters of mode in out can be both read and written. This clearly corresponds with the intended interpretation of the parameters in the examples: a procedure to solve a quadratic equation needs to read three coefficients and to write back two roots; a sort procedure is invoked in order to read and modify the actual parameter.
From the point of view of software engineering (reliability of interfaces between team members), in is superior to out which in turn is superior to in out. Specifying a mode of higher risk is acceptable only if the functionality it offers is required.
The following paragraph summarizes the parameter passing mechanism actually used in Ada, and may be skipped without loss of continuity.
Even though the above specification is sufficient to program in Ada, the standard goes on to specify the required implementation ([1], §6.2). Scalar parameters such as numbers and pointers must be implemented by copy: copy-in upon procedure entry for in and in out modes, and copy-out at the end of the procedure for out and in out modes. Structures such as tasks (concurrent processes) that have no meaning as values must be passed by reference. However, a compiler may use either copy or reference to implementation parameter passing for arrays and records. It is possible to write clever programs that produce different results under different implementations; such programs are simply not portable.
4 What should we do in Pascal?
Beginning students should be taught that reliability is one of the most important criteria in choosing programming structures. Thus call by value should always the preferred mode for parameter passing in Pascal, unless the functionality of reference is required.
For example, the declaration of a search procedure would be:
procedure Search(
V: Vector; Key: Float; var Found: Integer);
where only the returned index is a var parameter. The vector itself is passed by value since it is not modified. A sort procedure would, of course, pass the vector by reference:
procedure Sort(var V: Vector);
The implicit mapping from Ada modes to Pascal modes is that in parameters are equivalent to call by value, and out and in out parameters are equivalent to call by reference. It is also a good idea to carry the equivalence further and to refrain from modifying value parameters, as this can only confuse a student.
C++is similar to Pascal in that an unadorned parameter is passed by value, while the ampersand sign is used to indicate reference parameters. In Pascal, we use the term “var-parameter” to avoid the explicit word “reference”; similarly, in C++, one could use the term “ampersand-parameter”. Furthermore, C++supports declaration of parameters as const which should be appended to all value parameters to emphasize the one-way passing of data from the caller to the function. Unfortunately, C++cannot pass an array by value. Thus you should prefer a (safe) implementation of an array type within a class to predefined arrays.
5 E fficiency!
One often hears that the most common cause of bugs is clever coding aimed at writing efficient programs. Modern software engineering practice dictates that: (i) efficiency
Next statement A B Temp Output
Temp := A 3 4 ?
A := B 3 4 3
B := Temp 4 4 3
4 3 3
Figure 1: Tracking table
be only a secondary concern to correctness, (ii) efficiency improvement be undertaken only at as a result of actual measurements (and only at places indicated by the mea- surement), and (iii) efficiency is best served by choosing better algorithms and not by tinkering with the program code.
Conventional wisdom holds that arrays should be passed as var parameters rather than as value parameters because var parameters are “more efficient”: you do not have to copy the entire array. In an attempt to verify this claim, I wrote a program that passed a 25,000 byte array as a parameter to a procedure that computed the sum of the elements. The procedure was repeatedly called in a loop to ensure that the program ran long enough for easy measurement. I could not measure any run-time difference between value and reference passing of the parameter!
Contrary to conventional wisdom, it can be more efficient to use value parame- ters. The reason is that copying an array is typically implemented by a single efficient block-copy instruction. Most procedures, however, will repeatedly access the formal parameter: think of an elementary sort procedure which will access each of n elements approximately n times. Access to a value parameter in the activation record of the procedure is much more efficient than an access to a reference parameter. The latter requires an extra instruction for the indirect reference, and this can overwhelm any savings obtained by passing a reference as opposed to copying a value.
Thus it seems that the only valid efficiency-related reason for using reference pa- rameters is to save memory on the stack. However, depth of nesting of procedures is usually very small, even in recursive procedures (since they are typically written to im- plement algorithms that traverse data structures of depth log n). Increasing the stack by 10K or so, should cover the additional memory required to pass most, if not all, read- only parameters by value. Efficiency concerns are only relevant when the parameter size is very large, that is, many thousands of bytes. Student programs obviously do not meet this criterion.
6 Tracking tables
In our course, tracking tables are used to model the progress of a computation. Each line of a table contains the “instruction counter”—the next instruction to be executed, and the current values of all the variables. For example, the following table in Figure 1 shows the computation of three assignment statements, assuming that A and B have been initialized to 3 and 4, respectively, and Temp is not initialized.
The extension to value parameters is immediate: additional columns are added to the table. The columns are labeled with the names of the formal parameters and initialized with the values of the actual parameters. We demonstrate the extension on the following program which swaps the values of its input (incorrectly since the parameters are value parameters):
Next statement X Y Output readln(X,Y) ? ?
Swap(X,Y) 3 4
A B Temp
Temp := A 3 4 3 4 ?
A := B 3 4 3 4 3
B := Temp 3 4 4 4 3
3 4 4 3 3
writeln(X,Y) 3 4
3 4 3 4
Figure 2: Tracking table with value parameters
program P;
var X, Y: Integer;
procedure Swap(A, B: Integer);
var Temp:
begin
Temp := A;
A := B;
B := Temp;
end;
begin
readln(X, Y);
Swap(X, Y);
writeln(X, Y) end.
The tracking table is shown in Figure 2. Note how the value parameters and local variables are created upon entrance to the procedure and destroyed upon exit.
So far, so good: the table clearly demonstrates the concept of stack allocation with- out discussing the underlying implementation. To continue the use of these diagrams for reference parameters would require that columns contain “arrows” to the columns representing the global variables, but this introduces the implementation issues that we wish to avoid. Instead, the columns for the actual parameters are renamed with the names of the actual parameters. The tracking table is shown in Figure 3, assuming that the parameters of Swap are now correctly written as var parameters.
Renaming the actual parameters is not only easy to explain and understand, it is also consistent with the actual implementation of reference parameters as seen by the common use of the word “alias” in this context. To be truly precise, we should say that the formal parameter is an additional name for the actual parameter. In our course, the difference is moot: to encourage good software engineering practice, we do not allow the students to access global variables.
Next statement X Y Output readln(X,Y) ? ?
Swap(X,Y) 3 4
A B Temp
Temp := A 3 4 ?
A := B 3 4 3
B := Temp 4 4 3
4 3 3
X Y
writeln(X,Y) 4 3
4 3 4 3
Figure 3: Tracking table with reference parameters
7 Conclusion
Parameter passing is one of the most difficult concepts that a beginning student of pro- gramming has to learn. We recommend that the student be taught to choose a parameter passing mode based on the criterion of intended use, and that reference parameters be disguised as renamings. Only as they advance in their studies, should the implementa- tion and efficiency of parameter passing be analyzed.
Acknowledgement
I would like to thank Orna Lichtenstein for the many discussions we had on this topic.
References
[1] Intermetrics. Ada 95 Language Reference Manual, 1995. ANSI/ISO/IEC 8652:1995.
[2] Eliot B. Koffman. Pascal: Problem Solving and Program Design (Fourth Edition).
Addison-Wesley, Reading, MA, 1992.