# Functions

## Overview

Functions are the fundamental way programming languages split code into multiple units. Some languages use the term "function" and others use other terms:

• Procedure
• Subprogram
• Method
• Routine
• Subroutine

Some of these terms have slightly specialized meanings, but we will use "function" to mean any of these.

Functions:

• Have a single entry point.
• Have control transfered to them when they are called.
• Return control to their caller when they are finished.

Function terminology:

• Body

The code that comprises the function.

• Signature

The type and order of the functions parameters. This makes up the type of the function.

• Call

The piece of code that invokes the function, transferring control to it.

The first line (typically) of the function giving the name and parameter information.

## Parameters

Parameters allow callers to pass information to a function. There are two terms relating to parameters:

• Formal Parameters

Formal parameters are those that are listed in the function's header and used in the body.

• Actual Parameters

Actual parameters are the values that are passed by the caller.


int add(int a, int b) {
return a + b;
}

int main() {
int x = add(3, 7);
}


In the code above, a and b are formal parameters and 3 and 7 are actual parameters. There are two ways to match actual parameters to formal ones:

• By Position

The first actual parameter is matched to the first formal one, and so on. The most common method.

• By Keyword

The actual parameters are matched by name to formal parameters.

Python allows both methods:


def function(name, age, height):
print("Name is", name)
print("Age is", age)
print("Height is", height)

# by position
function("Bob", 42, 6.0)

# by keyword
function(height = 5.5, age = 31, name = "John")


Most languages allow for default values for parameters that are not specified.

Parameters can be passed in different ways:

• By Value

Values are copied into functions. Changes in the function do not affect the caller.

• By Reference

The address of parameters are passed in to the function. Changes in the function do affect the caller.

• By Name

The actual text in the function call is substituted into the function. Used for macros.

## Macros

C and C++ allow for macros. Unfortunately, macros in these languages are difficult to write correctly.

Below is a simple macro for multiplying two numbers:


#define TIMES(a, b) a * b


A problem with this macro is that it does not enforce precedence, so the following call will not produce what we want:


printf("5 * 7 = %d\n", TIMES(3 + 2, 3 + 4));


We can fix it by enforcing precedence with parenthesis:


#define TIMES(a, b) (a) * (b)


Even with this trick, macros can lead into problems. What is happening with this code:


#define MAX(a, b) ((a) > (b)) ? (a) : (b)

int main() {
/* what will go wrong now? */
int x = 5;

int largest = MAX(x++, 2);

printf("x = %d\n", x);

return 0;
}


Macros can be (ab)used for some very interesting code, as in this example:


#include <iostream>
using namespace std;

#define MAKEVAR(type, name) \
private: \
type name; \
public: \
type get_##name() {return name;} \
void set_##name(type o) {name = o;}

class Circle {
// make some variables automatically!
MAKEVAR(int, x)
MAKEVAR(int, y)
};

int main() {
Circle c;
c.set_x(10);
c.set_y(5);

cout << c.get_x() << ", " << c.get_y() << " " << c.get_radius() << endl;

return 0;
}


Function overloading is when multiple functions have the same name. This is allowable in C++, Java and C#.

Function overloading requires that the parameters be different in number and/or type.

Operator overloading allows programmers to specify how operators work with different types. Many languages allow operator overloading. Most only allow operators to be overloaded for new types.

Ruby is one of very few languages that allow built-in operators to be changed.


class Fixnum
def +(y)
# change how addition works!
return (self * y) - 1
end
end

# this will print 11 instead of 7
puts (3 + 4)


## Function Values

It is sometimes handy to treat functions as values inside of a program. This means that functions can be stored in variables, put in data structures or passed to or from functions.

One example is writing a sort function that takes a comparison as a parameter. This can be done easily in Python which has functions as values:


# bubble sort
def sort(data, compare):
sorted = False
while not sorted:
sorted = True
for index in range((len(data) - 1)):
if compare(data[index], data[index + 1]):
sorted = False
temp = data[index]
data[index] = data[index + 1]
data[index + 1] = temp

# one comparison function
def less(a, b):
return a < b

# call sort and pass the less function
sort(nums, less)


Another common use of passing functions is callbacks which are used in GUI development.

Functions can also be put in variables, lists and so on. These techniques are used in functional programming extensively.

## Function Pointers

C and C++ do not allow functions to be used as values directly, but they do allow function pointers. A function pointer is defined as a normal function exept for a * before the name:


return-type (*function-name)(parameter1type, parameter2type...)


To get a function pointer, we can use the & operator. The sort example in C++ would look like this:


void sort(int array[], int size, bool (*compare)(int, int)) {
// for each element
for(int i = 0; i < size; i++) {
// for each element after this
for(int j = i; j < size; j++) {
// if compare says out of order,
if(compare(array[i], array[j])) {
// swap them
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}

bool less(int a, int b) {
return a < b;
}

sort(nums, size, &less);


## Anonymous Functions

When using functions as values, it can become tedious to write and name functions for each one that we want. Many languages allow anonymous functions, also called lambda functions.

In Python this is done with the lambda keyword:


sort(nums, lambda a, b: a > b)


The new C++ 11 standard adds lambda functions to C++:


sort(nums, size, [](int a, int b) {return a > b;});


## Generic Functions

Generic functions allow for writing functions that work for multiple types of data in statically typed languages. C++ provides templates for this purpose:


template <typename T>
T max(T a, T b) {
return a > b a : b;
}


Templates are filled in with the appropriate types by the compiler.

Java provides generics which provide the same service:


public static <T> max(T a, T b) {
return a > b;
}


While they look similar, templates and generics work differently. Generics only produce one function and the actual types are filled in at runtime. Generics also only allow class types.

## Nested Functions

In many languages, functions can be nested inside of other functions. This is possible in Pascal, Ada, Javascript, Python, Ruby and most functional languages.

The following Python code calculates all prime numbers in a range. To do this it uses a nested function


# return all prime numbers from 1 to n
def primes(n):
# test if a number is prime in a nested function
def isPrime(x):
for i in range(2, x // 2 + 1):
if x % i == 0:
return False
return True

# go through numbers
nums = []
for i in range(1, n + 1):
if isPrime(i):
nums.append(i)
return nums


Nested functions can access the local variables of their enclosing function.

## Closures

One use of nested functions is to create closures. A closure is a function that can reference its enclosing environment from another point. A simple example:


# return a counter function
def counter(start, step):
i = start - step
def c():
nonlocal i
i += step
return i
return c

# create counter functions
counter1 = counter(1, 1)
counter2 = counter(100, -1)


The functions returned from counter are closures because they contain elements of the call that produced them.

Below is the same closure implemented in Racket:


(define (counter start step)
(define i (- start step))
(lambda ()
(begin
(set! i (+ i step))
i)))

(define counter1 (counter 1 1))
(define counter2 (counter 100 -1))