CSE 505 Lecture Notes:
Parameter Passing
October 12, 1994
Introduction
techniques used for argument passing:
- call by value
- call by result
- call by value-result
- call by reference
- call by name
call by value:
copy going into the procedure
call by result:
copy going out of the procedure
call by value result:
copy going in, and again going out
call by reference:
pass a pointer to the actual parameter, and indirect through the pointer
call by name:
re-evaluate the actual parameter on every use. For actual parameters
that are simple variables, this is the same as call by reference. For
actual parameters that are expressions, the expression is re-evaluated on
each access. It should be a runtime error to assign into a formal
parameter passed by name, if the actual parameter is an expression.
Implementation: use anonymous function ("thunk") for call by
name expressions
efficiency of call by reference -- large arrays
Fortran uses call by reference
insecurities in early FORTRANs -- passing a constant
Algol 60 has call by name, call by value
Ada uses different designations: IN
, OUT
,
IN OUT
:
- For scalar data types (such as integers),
IN
is the same as
call by value, OUT
is the same as call by result, and IN
OUT
is the same as call by value result. In addition,
IN
parameters are local constants -- you can't assign into them.
-
For compound data types (such as arrays), these can be implemented as
above, or using call by reference. (You can write a test program to
determine which method your compiler is using -- however, programs that
rely on one implementation choice or the other are "erroneous".)
Lisp and Smalltalk use call-by-value with pointer semantics
An important related concept: aliasing. Two variables are
aliased if they refer to the same storage location. A common way that
aliasing can arise is using call by reference. A formal parameter can be
aliased to a nonlocal variable, or two formal parameters can be aliased.
In a functional programming language, call by value is equivalent to
applicative order evaluation. Call by name is equivalent to normal order
evaluation. (It always gives the same results as lazy evaluation, but lazy
evaluation may be faster.)
Example 1: Call by value and Call by name
begin
! Simula program to demonstrate call by value and call by name;
! (Algol-60 would be similar);
integer a,b;
integer procedure IncrementByValue (x); integer x;
begin
x := x+2;
IncrementByValue := x;
end;
integer procedure IncrementByName (x); name x; integer x;
begin
x := x+2;
IncrementByName := x;
end;
integer procedure AddByValue (x); integer x;
begin
AddByValue := x+x;
end;
integer procedure AddByName (x); name x; integer x;
begin
AddByName := x+x;
end;
a := 3;
b := AddByValue(IncrementByValue(a));
outint(a,5); outint(b,5); outimage;
a := 3;
b := AddByValue(IncrementByName(a));
outint(a,5); outint(b,5); outimage;
a := 3;
b := AddByName(IncrementByValue(a));
outint(a,5); outint(b,5); outimage;
a := 3;
b := AddByName(IncrementByName(a));
outint(a,5); outint(b,5); outimage;
end;
Output:
AddByValue IncrementByValue a=3 b=10
AddByValue IncrementByName a=5 b=10
AddByName IncrementByValue a=3 b=10
AddByName IncrementByName a=7 b=12
Example 2: illustrates call by value, value-result, reference
begin
integer n;
procedure p(k: integer);
begin
n := n+1;
k := k+4;
print(n);
end;
n := 0;
p(n);
print(n);
end;
Note that when using call by reference, n
and k
are aliased.
Output:
call by value: 1 1
call by value-result: 1 4
call by reference: 5 5
Example 3: Non-local references
procedure clam(n: integer);
begin
procedure squid;
begin
print("in procedure squid -- n="); print(n);
end;
if n<10 then clam(n+1) else squid;
end;
clam(1);
Output:
in procedure squid -- n=10
Example 4: Procedures as parameters
To pass a procedure as a parameter, the system passes a closure: a
reference to the procedure body along with a pointer to the environment of
definition of the procedure.
begin
procedure test(n: integer, p: procedure);
begin
procedure rose;
begin
print("in procedure rose -- n="); print(n);
end;
print("in procedure test -- n="); print(n);
p;
if n<10 then
begin
if n=3 then test(n+1,rose) else test(n+1,p)
end
end;
procedure violet;
begin
print("in procedure violet");
end;
test(1,violet);
end;
Output:
in procedure test -- n=1
in procedure violet
in procedure test -- n=2
in procedure violet
in procedure test -- n=3
in procedure violet
in procedure test -- n=4
in procedure rose -- n=3
in procedure test -- n=5
in procedure rose -- n=3
in procedure test -- n=6
in procedure rose -- n=3
in procedure test -- n=7
in procedure rose -- n=3
in procedure test -- n=8
in procedure rose -- n=3
in procedure test -- n=9
in procedure rose -- n=3
in procedure test -- n=10
in procedure rose -- n=3
Similar effects can be achieved by passing labels as parameters.