CPS 343/543 Lecture notes: Parameter-passing mechanisms
Coverage: [EOPL] §3.8 (pp. 107-114)
call-by-value vs. call-by-reference
- sample program on p. 108
- references a and x are distinct
- graphical depiction of call-by-value (result is 3)
- graphical depiction of call-by-reference (result is 4)
- C only supports call-by-value
- in C we simulate call-by-reference by
passing the address of a variable by value
#include<stdio.h>
/* swap call-by-value */
void swapCbV (int x, int y) {
int temp = x;
x = y;
y = temp;
}
/* swap call-by-reference */
void swapCbR (int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp;
}
main() {
int a = 1;
int b = 2;
swapCbV (a, b);
printf (" call-by-value: ");
printf ("a = %d, b = %d\n\n", a, b);
swapCbR (&a, &b);
printf ("call-by-reference: ");
printf ("a = %d, b = %d\n\n", a, b);
}
- why cannot a swap function be written in Java?
- why might we want to use call-by-reference? to simulate
the return of more than one value
- FORTRAN was the first language to use call-by-reference
Implementing call-by-reference in our interpreter
- currently are interpreter only supports call-by-value. why?
because every time we encounter an operand, we create a new reference
- call-by-value: create new reference for every evaluation of an operand
- call-by-reference:
create new reference for only evaluation a non-variable operands
- let's retain
denoted value = ref(expressed value)
expressed value = number + procvalue
- we only create a new reference for non-variable
operands (e.g., literals)
New implementation of references
- now the vector element to which reference refers can contain
either an expressed value or denoted value (i.e.,
a reference to an expressed value)
- the former is called a direct target while
the latter is called an indirect target
- new reference implementation in Fig. 3.17 on p. 111
(regenerated from [EOPL] Fig. 3.18 on p. 113)
Re-instrumentation of eval-rand
- the procedures extend-env and apply-env-ref
need not change
- consider where subexpressions are evaluated:
- primitive applications,
- let's, and
- user-defined procedure applications
- we use call-by-value for the first two and call-by-reference
for the last
- code for primitive applications on p. 110 (essentially same as
original)
- code for let's on p. 112 (essentially same as
original)
- code for user-defined procedure applications on p. 112 (now
eval-rand has changed):
(define eval-rand
(lambda (rand env)
(cases expression rand
;; if the operand is a variable, then it denotes a location
;; containing an expressed value, so we want to return an
;; _indirect target_ pointing to that location
(var-exp (id)
(indirect-target
(let ((ref (apply-env-ref env id)))
(cases target (primitive-deref ref)
;; if the variable is bound to a _location_ which
;; contains a direct target, we return
;; an indirect target to that location
(direct-target (expval) ref)
;; but if the variable is bound to a _location_
;; which contains an indirect target, then
;; we return the same indirect target
(indirect-target (ref1) ref1)))))
;; if the operand is a non-variable, then we create a new
;; location, as before, by returning a _direct target_ to it
;; (i.e., call-by-value)
(else (direct-target (eval-expression rand env))))))
3 cases:
- operand is a non-variable (e.g., literal): return a direct target to it
- operand is a var-exp which points to a direct target:
return an indirect target to it
- operand is a var-exp which points to a indirect target:
return an copy of the same indirect target
Illustrative example on p. 113
Call-by-result
Call-by-value-result
- combination of call-by-value and call-by-result,
and shares the problems of both
- sometimes referred to as call-by-copy-restore
Sample code snippet
note: Pascal-style code is used only
for illustration; use not intended to convey that
Pascal uses these mechanisms.
procedure p (integer x, integer y) begin
x = x + 1;
y = y + 1;
end;
begin
a = 1;
p (a, a);
(* what is the value of a here? *)
print a;
(* if call-by-value used, a=1
if call-by-value-result, a=2
if call-by-reference used, a=3
*)
end.
Simple classification
to think about each of the parameter-passing mechanisms
- call-by-value (IN)
- call-by-result (OUT)
- call-by-value-result (also called call-by-copy)
- IN at the front
- OUT at the back
- call-by-reference (IN-OUT)
- call-by-name
- lazy evaluation
- akin to #define in C
call-by-value-result (IN-OUT) != call-by-reference (IN-OUT)
References
| [COPL] |
R.W. Sebesta.
Concepts of Programming Languages.
Addison-Wesley, Boston, MA, Sixth edition, 2003. |
| [EOPL] |
D.P. Friedman, M. Wand, and C.T. Haynes.
Essentials of Programming Languages.
MIT Press, Cambridge, MA, Second edition, 2001. |
|