Functions: 2.1 The Concept of Functions
Functions: 2.1 The Concept of Functions
Functions
System.out.print("Flight ");
System.out.print("819");
System.out.print(" to ");
System.out.print("Tokyo");
System.out.print(" takes off at ");
System.out.println("8:50 AM");
System.out.println();
System.out.println();
System.out.println();
System.out.print("Flight ");
System.out.print("211");
System.out.print(" to ");
System.out.print("New York");
System.out.print(" takes off at ");
System.out.println("8:55 AM");
System.out.println();
System.out.println();
System.out.println();
System.out.print("Flight ");
System.out.print("211");
System.out.print(" to ");
System.out.print("New York");
System.out.print(" takes off at ");
System.out.println("8:55 AM");
jumpThreeLines();
The statement jumpThreeLines(); that is found in the main program is
named the call of the function jumpThreeLines. The statement that is found in
the function and that is executed on each call is named the body of the function.
Organising a program into functions allows you to avoid repeated code,
or redundancy. As well, it makes programs clearer and easier to read: to un-
derstand the program above, it isn’t necessary to understand how the function
jumpThreeLines(); is implemented; you only need to understand what it does.
This also allows you to organise the structure of your program. You can choose
to write the function jumpThreeLines(); one day, and the main program an-
other day. You can also organise a programming team, where one programmer
writes the function jumpThreeLines();, and another writes the main program.
This mechanism is similar to that of mathematical definitions that allows
you to use the word ‘group’ instead of always having to say ‘A set closed under
an associative operation with an identity, and where every element has an
inverse’.
2.1 The Concept of Functions 21
2.1.2 Arguments
Some programming languages, like assembly and Basic, have only a simple
function mechanism, like the one above. But the example above demonstrates
that this mechanism isn’t sufficient for eliminating redundancy, as the main
program is composed of two nearly identical segments. It would be nice to
place these segments into a function. But to deal with the difference between
these two copies, we must introduce three parameters: one for the flight number,
one for the destination and one for the take off time. We can now define the
function takeOff
a = 3;
b = 4;
c = 5;
d = 12;
u = Math.sqrt(a * a + b * b);
v = Math.sqrt(c * c + d * d);
static int x;
static T1 x1 = t1 ;
...
26 2. Functions
static Tn xn = tn ;
However, in Java, the main program is placed inside a special function called:
main. The main function must not return a value, and must always have an
argument of type String []. In addition to the keyword static, the definition
of the main function must also be preceded by the keyword public.
In addition, the program must be given a name, which is given with the
keyword class. The general form of a program is:
class Prog {
static T1 x1 = t1 ;
...
static Tn xn = tn ;
For example
class Hypotenuse {
In C, the main program is also a function called main. For historical reasons,
the main function must always return an integer, and is usually terminated with
return 0;. You don’t give a name to the program itself, so a program is simply
a series of global variable and function declarations.
int main () {
printf("%f\n",hypotenuse(3,4));
return 0;}
class Prog {
static int n;
The value of the expression f(6) is 15. The function f adds the global vari-
able n, which has been initialised to 4 in the main program, the local variable
p, with a value of 5, and the argument x, with a value of 6.
In contrast, the value of the expression g(6) is 16, because both occurrences
of n refer to the local variable n, which has a value of 5. In the environment
in which the body of function g is executed, the global variable n is hidden by
the local variable n and is no longer accessible.
28 2. Functions
2.1.9 Overloading
In Java, it is impossible to define two functions with the same name, for example
static int f (final int x) {
return x;}
where
p0 = if (b) giveup; else skip;
and pn+1 = if (b) {q pn } else skip;.
32 2. Functions
– Finally, we add the case of functions, which is very similar to the case of
functions in the definition of the evaluation of expressions, except that if the
object Σ(p,e”,m”,G) has the form (normal,m”’), then we let
a b u x y
Next, we execute the body of the function, which produces the result
(return,5.0,m”) and so Θ(hypotenuse(a,b),e,m,G) is (5.0,m”). The result
of the execution of the statement u = hypotenuse(a,b); is then an ordered
pair composed of a boolean normal and the memory state m”’ = [r1 = 3.0,
r2 = 4.0, r3 = 5.0, r4 = 3.0, r5 = 4.0].
The value of the variable u in the state e, m”’ is 5.0.
2.2 The Semantics of Functions 33
Exercise 2.3
What happens if the formal arguments x and y of the function hypote-
nuse are constant variables?
Exercise 2.4
What happens if you execute the statement u = hypotenuse(a,b);,
with the variables a, b, and u declared in the main function?
Finally, we can give the definition of the Σ function for the entire program.
Let P be a program formed of global variable declarations static T1 a1 = t1 ;,
..., static Tn an = tn ; and of function declarations static U1 f1 (x1 ) p1 ;,
..., static Un fn (xn ) pn ;.
Let v1 , ..., vn be the initial values given to global variables, that is to say the
values of expressions ti . Let e be the environment [a1 = v1 , a2 = r2 , ...,
an = rn ] in which we associate the global variable ai to the value vi or to the
reference ri whether it is constant or mutable, and m is the memory state [r2
= v2 , ..., rn = vn ], in which we associate the references ri associated to
mutable global variables with the values vi . Let G be the global environment
(e, [f1 = (x1 ,p1 ), ..., fn = (xn ,pn )]).
The memory state Σ(P) is defined by
– Σ(P) = Σ(main(null);,e,m,G)
where null is a value of type String [] which we will discuss later.
Exercise 2.5
The function f is defined as follows
Since expressions can modify memory, consideration must be given to the fact
that in the definition of Σ we have given, arguments of a function are evaluated
from left to right. So, we evaluate t1 in the memory state m, and t2 in the
memory state m1 produced by the evaluation of t1 , ... So, the program
class Prog {
static int n;
2.2.4 Caml
The definition of the function Σ for Caml is somewhat different from the defini-
tion of Σ used for Java. In Caml, all formal arguments are constant variables,
so new references are never created at the point of a function call.
Also, in Caml, there is only one name space for functions and variables. In
Java, the program
class Prog {
static int f = 4;
static int x = 4;
let n = ref 0
in let f x y = x
in let g z = (n := !n + z; !n)
in print_int (f (g 2) (g 7))
2.2.5 C
The definition of the Σ function for C is also somewhat different from the
definition of Σ for Java.
In C, the references created at the moment of a function call are removed
from the memory and the end of the execution of the body of the function.
Like in Caml, there is only one name space for functions and variables, and
functions are declared in the same environment as variables. In this environ-
ment, we not only associate the name f to the list of formal arguments and the
body of the function, but also to the environment e to extend with the arguments
for executing the body of the function. This environment is, like in Caml, the
environment of the definition of the function. For example, the program
int f () {return x;}
int x = 4;
int main () {
printf("%d\n",f());
return 0;}
is invalid.
C compilers also evaluate a function’s arguments from left to right, as in
Java. However, the definition of the language, like that of Caml, does not specify
the order of evaluation of a function’s arguments, and it is up to the programmer
to write programs whose result does not depend on the order of evaluation.
Exercise 2.8
Give the definition of the Σ function for C, assuming that arguments are
always evaluated from left to right.
2.3 Expressions as Statements 37
class Prog {
static int a;
static int b;
a b x y
4 7 4 7
2.4 Passing Arguments by Value and Reference 39
The values of the variables x and y are exchanged, which results in the mem-
ory state [r1 = 4, r2 = 7, r3 = 7, r4 = 4, r5 = 4] which returns control
to the main program. The environment is then e = [a = r1 , b = r2 ] with
the memory state [r1 = 4, r2 = 7, r3 = 7, r4 = 4, r5 = 4]. The values
of the variables a and b have not changed.
In other words, the function swap ignores the variables a and b. It can only
use their value at the moment of the function call, and cannot modify their
value: executing the statement swap(a,b); has the same result as executing
the statement swap(4,7);.
The mechanism of argument passing that we have described is called argu-
ment passing by value. It does not allow the creation of a swap function that
changes the contents of two variables. However, most programming languages
have a construct that allows the creation of such a function. But, this construct
is somewhat different in each language. Before seeing how this is done in Java,
Caml, and C, we will look at the much simpler example of the Pascal language.
2.4.1 Pascal
a x b y
4 7
Because of this, the procedure swap exchanges the contents of the references r1
and r2 and not of the references r3 and r4
a x b y
7 4
and after execution of the procedure, the contents of the references associated
with the variables a and b have been exchanged.
Being able to explain the mechanism of passing by reference is the main
motivation for decomposing the state into an environment and a memory state
by introducing an intermediate set of references, as we have done in the previous
chapter.
Exercise 2.10
Give the definition of the Σ function in the case of functions with an
argument passed by reference.
2.4.2 Caml
a:= 4;
b := 7;
swap a b;
print_int !a;
print_newline();
print_int !b;
print_newline()
Indeed, when we call the function swap a b in the environment [a = r1 , b =
r2 ] and the memory state [r1 = 4, r2 = 7], we create the environment [a =
r1 , b = r2 , x = r1 , y = r2 ] in which the constant formal arguments x and
y are linked to the real arguments r1 and r2 and we keep the same memory
state [r1 = 4, r2 = 7]
a x b y
4 7
and the function swap exchanges the contents of the references r1 and r2 and
after the execution of the function, the contents of the references associated
with the variables a and b have now also been exchanged.
Exercise 2.11
What does the following program do?
2.4.3 C
int main () {
int x;
int* u;
x = 4;
u = &x;
printf("%d\n",*u);
return 0;}
u x
a x b y
4 7
And, the function swap exchanges the contents of the references r1 and r2 and
after the execution of the function, the contents of the references associated
with the variables a and b have been exchanged.
In this example, take note of the syntax of the declaration of the argu-
ment x, int* const x, which prevents the assignment x = t; but allows the
assignment *x = t;. The declaration const int* x, in contrast allows the as-
signment x = t; but prevents the assignment *x = t;. The declaration const
int* const x prevents both types of assignment.
Exercise 2.14
What is the output of the following program?
*x = *y;
*y = z;}
int main () {
a = 4;
b = 7;
swap(&a,&b);
printf("%d\n",a);
printf("%d\n",b);
return 0;}
Exercise 2.16
Give the definition of the Θ function for expressions of the form *t and
&x, and the definition for the Σ function for statements of the form *t
= u;.
Exercise 2.17
The goal of this exercise is to demonstrate that, in C, you may look for
a reference that does not exist.
1. In the following Caml program, what is the state in which the state-
ment print_int !(!u) is executed?
let f p = let n = ref p in let x = ref n in !x
in let u = ref (f 5)
in print_int !(!u)
Answer the same question for the following program.
let f p = let n = ref p in let x = ref n in !x
in let u = ref (f 5)
in let v = ref (f 10)
in print_int !(!u)
2.4 Passing Arguments by Value and Reference 45
int main () {
int* u = f(5);
printf("%d\n",*u);
return 0;}
In what state is the statement printf("%d\n",*u); executed?
Hint: remember that in C, in contrast to Caml, we remove from
memory the reference associated with a variable when that variable
is removed from the environment.
3. In C, when we use a reference that is not declared in memory, it
does not produce an error, and the result will be unpredictable. Try
compiling and running the following C program.
int main () {
int* u = f(5);
int* v = f(10);
printf("%d\n",*u);
return 0;}
2.4.4 Java