advanced programming parameter passing giuseppe attardi università di pisa
TRANSCRIPT
Advanced ProgrammingAdvanced Programming
Parameter PassingParameter Passing
Giuseppe AttardiGiuseppe Attardi
Università di PisaUniversità di Pisa
Parameter PassingParameter Passing
Parameter PassingParameter Passing
Call by valueCall by valueCall by referenceCall by referenceCall by result, value/resultCall by result, value/resultC++ referencesC++ referencesClosures as parametersClosures as parametersCall by nameCall by nameLabel parametersLabel parametersVariable number of argumentsVariable number of argumentsFunction returnsFunction returns
TerminologyTerminology
Expressions evaluate to R-valuesVariables and components of
variables of structured types also have an L-value, that is, an address where their R-value is stored
The assignment statement requires an L-value on the left-hand side (L stands for “left”) and an R-value on the right-hand side (R stands for “right”)
int x = 3;int x = 3;x = x;x = x;int v[40];int v[40];v[3] = v[3]v[3] = v[3]
(x == 3) =(x == 3) =3 = 3 = int foo();int foo();
foo = ….foo = ….point.x = 12;point.x = 12;
Value model, reference modelValue model, reference model
b = 2;b = 2;
c = b; b = b +1;c = b; b = b +1;
a = b + c;a = b + c;
5
2
2
a
b
c
a
b
c
Value model Reference model 6
3 2 3
ExampleExample
class Point { int x, y; }class Point { int x, y; }
Point p = Point(3, 4);Point p = Point(3, 4);
Point p2 = p;Point p2 = p;
p.x = 5;p.x = 5;
p2.x ?p2.x ?
foo(p);foo(p);
int i = 3;int i = 3;
Integer I = new Integer(3);Integer I = new Integer(3);
CC
void foo (int* x) {void foo (int* x) {*x = 3;*x = 3;}}
struct Point { int x, y};struct Point { int x, y};
void bar(Point* p) { p->x = 3; }void bar(Point* p) { p->x = 3; }Point p; p.x = 5;Point p; p.x = 5;Point* p2 = &p;Point* p2 = &p;bar(p2);bar(p2);
Reference modelReference model
In language using reference model, In language using reference model, every variable is a L-valueevery variable is a L-value
When it appears in a R-value context, When it appears in a R-value context, it must be it must be dereferenceddereferenced
Usually dereference is implicitUsually dereference is implicitExamples:Examples:– Algol68, Lisp, ML, Haskell, SmallTalk
Java: mixed (value for built-in types)Java: mixed (value for built-in types)
Call by valueCall by value
The value of the R-value of the actual The value of the R-value of the actual parameter is copied into the formal parameter is copied into the formal parameter at invocationparameter at invocation
Call by resultCall by result
The value of the formal parameter is The value of the formal parameter is copied into the actual parameter copied into the actual parameter (which must have an L-value) at (which must have an L-value) at procedure return.procedure return.
Call by value/resultCall by value/result
The parameter is treated as in value The parameter is treated as in value mode during invocation and as in mode during invocation and as in result mode during return.result mode during return.
foo (inout x) { … x …}foo (inout x) { … x …}
foo1 (ref x) { … x = x + 1; … }foo1 (ref x) { … x = x + 1; … }
foo1(v[3]);foo1(v[3]);s = “asdasd”;s = “asdasd”;foo1(s); // OKfoo1(s); // OKfoo1(“asdasd”); // KOfoo1(“asdasd”); // KOfoo1(3); // KOfoo1(3); // KOint y = 7;int y = 7;foo1(y);foo1(y);y?y?
foo2 (Point ref q) { q = new Point(); }foo2 (Point ref q) { q = new Point(); }
Point p = new Point(3,4);Point p = new Point(3,4);
Point prev = p;Point prev = p;
foo2(ref p);foo2(ref p);
p == prev?p == prev?
void foo (ref int x) {void foo (ref int x) {
x = x + 3;x = x + 3;
x = x/0;x = x/0;
} }
int z = 2;int z = 2;
foo(z);foo(z);
Call by referenceCall by reference
The L-value of the formal parameter The L-value of the formal parameter is set to the L-value of the actual is set to the L-value of the actual parameter.parameter.
The address of the formal parameter The address of the formal parameter is the same as the address of the is the same as the address of the actual parameter. Any assignment to actual parameter. Any assignment to the formal parameter immediately the formal parameter immediately affects the actual parameter.affects the actual parameter.
NoteNote
// C#// C#void foo(int ref x) { x += 1; }void foo(int ref x) { x += 1; }// C++// C++void foo(int& x) { x += 1; }void foo(int& x) { x += 1; }
int a[3];int a[3];a[0] = 0;a[0] = 0;foo(ref a[0]);foo(ref a[0]); // C#// C#foo(a[0]);foo(a[0]); // C++// C++
foo(p);foo(p);
C++ Reference DatatypeC++ Reference Datatype
C++ provides a C++ provides a Reference dataypeReference dataype, built from other , built from other typestypes
If T is a type T& is a new type called “reference to T”If T is a type T& is a new type called “reference to T” One should avoid the confusion between the general One should avoid the confusion between the general
concept of concept of referencereference and a and a Reference TypeReference Type Also avoid the confusion with the notion of Also avoid the confusion with the notion of Reference Reference
typestypes in Java and C# in Java and C# Reference Types are not pointers, even though they Reference Types are not pointers, even though they
are implemented through pointers and hence are implemented through pointers and hence accessing a reference type may involve an implicit accessing a reference type may involve an implicit dereference operationdereference operation
Using Reference Types in parameters even though Using Reference Types in parameters even though they are still passed by value.they are still passed by value.
Reference/Value TypesReference/Value Types
In programming language theory, a In programming language theory, a reference typereference type is a is a data type that can that can only be accessed by references only be accessed by references
Objects of a reference type are Objects of a reference type are always dynamically allocatedalways dynamically allocated
value type objects instead can be value type objects instead can be manipulated directly and are copied manipulated directly and are copied when moved (assignment, parameter when moved (assignment, parameter passing or function return)passing or function return)
C++ Reference Type ExampleC++ Reference Type Example
void foo(int& x) {void foo(int& x) {x = x + 1;x = x + 1;
}}
int y = 7;int y = 7;foo(y);foo(y);y ?y ?foo(3);foo(3); // only feasible if x was// only feasible if x was
// declared as const int&// declared as const int&
Call by nameCall by name
Every use of the formal parameter causes Every use of the formal parameter causes the actual parameter to be freshly the actual parameter to be freshly evaluated in the referencing environment evaluated in the referencing environment of the invocation point.of the invocation point.
If the formal parameter’s L-value is needed If the formal parameter’s L-value is needed (for example, the parameter appears on (for example, the parameter appears on the left-hand side of an assignment), the the left-hand side of an assignment), the actual parameter’s L-value must be freshly actual parameter’s L-value must be freshly evaluated.evaluated.
If the formal parameter’s Rvalue is needed, If the formal parameter’s Rvalue is needed, the actual parameter’s R-value must be the actual parameter’s R-value must be freshly evaluated.freshly evaluated.
Call by name: exampleCall by name: example
int sum(name int expr, name int j, int size)int sum(name int expr, name int j, int size)
{{
int tot = 0;int tot = 0;
for (; j < size; j++)for (; j < size; j++)
tot += expr;tot += expr;
return tot;return tot;
}}
sum(A[i], i, n); /* sum of vector elements */sum(A[i], i, n); /* sum of vector elements */
{ int i;{ int i;
int[] A;int[] A;
&int thunk() { return &A[i]; }&int thunk() { return &A[i]; }
sum(thunk, i, n);sum(thunk, i, n);
}}
Call by macroCall by macro
Every use of the formal parameter Every use of the formal parameter causes the text of the actual causes the text of the actual parameter to be freshly evaluated in parameter to be freshly evaluated in the referencing environment of the the referencing environment of the use point.use point.
#DEFINE foo(x) x + x#DEFINE foo(x) x + x
foo(read())foo(read())read() + read()read() + read()
inline int foo(int x) { return x + x; }inline int foo(int x) { return x + x; }
int foo(int& x, int &y) { x++; y++; return x + y;}int foo(int& x, int &y) { x++; y++; return x + y;}
Foo(a, a);Foo(a, a);
Parameter passing modesParameter passing modes
ImplementationImplementation OperationsOperations Change to Change to actual?actual?
Alias?Alias?
ValueValue ValueValue RWRW NoNo nono
In, constIn, const Value, Value, referencereference
RORO NoNo MaybeMaybe
Out (C#, Ada)Out (C#, Ada) Value, Value, referencereference
WOWO YesYes MaybeMaybe
Value/resultValue/result ValueValue RWRW YesYes NoNo
Var, refVar, ref ReferenceReference RWRW YesYes YesYes
SharingSharing Value, Value, referencereference
RWRW YesYes MaybeMaybe
In outIn out Value, Value, referencereference
RWRW YesYes MaybeMaybe
NameName ClosureClosure RWRW YesYes yesyes
EsercizioEsercizio
swap(x, y) using just call-by-valueswap(x, y) using just call-by-value
void swap(int x, int y) {void swap(int x, int y) { int temp;int temp; temp = x;temp = x; x = y;x = y; y = temp;y = temp;};};
Does not work.Does not work.
swap(x, y) using just call-by-nameswap(x, y) using just call-by-name
int b[10]; swap(i, b[i]);int b[10]; swap(i, b[i]);
void swap(name int x, name int y) {void swap(name int x, name int y) {
int temp;int temp;
temp = x;temp = x;
x = y;x = y;
y = temp;y = temp;
};};
Note on Note on
List l = new List();List l = new List();
Student s = new Student();Student s = new Student();
l.add(s);l.add(s);
float pi = 3.14;float pi = 3.14;
l.add(pi);l.add(pi);
(new Integer(314)).toString();(new Integer(314)).toString();
s.toString();s.toString();
NoteNote
int a[] = new int[3];int a[] = new int[3];int b[] = new int[5];int b[] = new int[5];swap(a, b);swap(a, b);aaswap(i, a[i]);swap(i, a[i]);
int temp; temp = x; x = y; y = temp;int temp; temp = x; x = y; y = temp;
a=3, b=5; a=5, b=5; a=5, b=3;a=3, b=5; a=5, b=5; a=5, b=3;void swap(inout int x, inout int y) {void swap(inout int x, inout int y) { int temp;int temp; temp = x;temp = x; x = y;x = y; y = temp;y = temp;};};
ExerciseExercise
swap(x, y) using just call-by-nameswap(x, y) using just call-by-name
swap(name x, name y) => {swap(name x, name y) => {
}}
Does it work?Does it work?
Call by nameCall by name
Counter example:Counter example:
swap(i, A[i])swap(i, A[i])
(i=3, A[3] = 4) => (i=4, A[4] = 4, A[3] (i=3, A[3] = 4) => (i=4, A[4] = 4, A[3] unchanged)unchanged)
Call by value/resultCall by value/result
swap(i, A[i])swap(i, A[i])works even in case (i=2, A[2]= 99)works even in case (i=2, A[2]= 99)
Call by valueCall by value
Copies argumentCopies argument Special cases:Special cases:
– array– struct
typedef struct { int x, y} Pair;Pair q;zed(q);
Pair foo() { Pair p; return p; }Pair p = foo();
stack.push_back(Pair(2,3));
int [200000] v;bar(v);std::string s; bad(s);
int* foo() {int* foo() {
int v[100];int v[100];
return v;return v;
}}
ClosuresClosures
First Class function objectsFirst Class function objects
Downward Closure in PascalDownward Closure in Pascal
Lexical Environment of Lexical Environment of FunctionsFunctionsBecause of nested lexical scope, Because of nested lexical scope,
even passing functions in Pascal even passing functions in Pascal requires passing the enclosing requires passing the enclosing lexical environmentlexical environment
Closure in PythonClosure in Python
def makeInc(x):def makeInc(x):def inc(y):def inc(y): return y + x return y + x
return increturn inc
inc3 = makeInc(3)inc3 = makeInc(3)inc10 = makeInc(10)inc10 = makeInc(10)inc3(5) # returns 8inc3(5) # returns 8inc10(5) # returns 15inc10(5) # returns 15
Closure as ClassesClosure as Classes
def makePair(x, y):def makePair(x, y):def get(arg):def get(arg): if arg == ‘x’:if arg == ‘x’: return xreturn x elif arg == ‘y’elif arg == ‘y’
return yreturn yreturn getreturn get
p = makePair(3, 5)p = makePair(3, 5)p(‘x’) -> 3p(‘x’) -> 3P(‘y’) -> 5P(‘y’) -> 5