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
Call by value is particularly efficient for small pieces of data (such integers), since they are trivial to copy, and since access to the formal parameter can be done efficiently.
Call by reference is particularly efficient for large pieces of data (such as large arrays), since they don't need to be copied.
Fortran uses call by reference
Insecurity in early FORTRANs -- passing a constant allowed the procedure
to change the constant!
Algol 60 has call by name, call by value
Ada uses different designations: IN
, OUT
,
IN OUT
:
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.
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.
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
begin array a[1..10] of integer; integer n; procedure p(b: integer); begin print(b); n := n+1; print(b); b := b+5; end; a[1] := 10; a[2] := 20; a[3] := 30; a[4] := 40; n := 1; p(a[n+2]); new_line; print(a); end;
Output:
call by reference: 30 30 10 20 35 40 call by name: 30 40 10 20 30 45