In the previous post that can be read here, we looked at repetition, the process of telling a computer to repeatedly execute a set of instructions based on some condition. In this article, we will delve into functions, what they are, how we use them, and how best to design functions in our programs.
Yet again, before we delve into functions, there are some things we need to know first. Mostly we need to look at statements and compound statements.
In most programming languages, the smallest element we can use to create a program is known as a statement, which up until now we have been calling an instruction. We have already looked at several different statements: if-statements, while-statements, and for-statements, but other statements exist such as assignment statement, assigning values to our variables, and expression statements, which is a statement that produces a value, for instance 5 + 5 * 2.
Often it takes more than a single statement to get something done, and that’s where compound statements, also known as blocks, come into play. If-statements, while-statements, and for-statements are all examples of compound statements. That is, they comprise of more than a single statement. In most programming languages, we define a block of code using a set of curly braces, so an if statement would look like the following:
// statements in here
The above example shows an if statement, and curly braces with all instructions within the curly braces being the ones that are executed if the condition evaluates to true.
There are two main benefits for using code blocks. They allow us to define scope, something I won’t be touching on in this article, and that as you have already seen, they allow us to group a set of statements. One thing we can’t do with our compound statements is use it multiple times throughout our program, which finally brings us nicely onto functions.
A function is like a named compound statement which can be referenced by its name throughout our code, and thus used multiple times. However, unlike a compound statement, our functions have additionally properties. They can accept and return data in the form of variables or data structures.
A function needs a name so we can identify it, like a variable does so we can access the memory location our data resides in, a function name is an identifier to the address were our group of statements are stored. As a function can accept and return data, we also must define this when creating our function. A name, return type and list of accepted data forms the signature of a function. Below is an example of a function:
int AddNumbers(int a, int b)
int c = a + b;
In the example shown we have created a function called AddNumbers which accepts two variables, also called parameters, called a and b, defined within a set of parentheses, and we have our return type defined as an int, placed before the name of the function. The idea behind this function is that it accepts two integer numbers, and then we add these two numbers together within the function and return the result.
There are no restrictions on the type of data our function returns, it can be a primitive type, or user-defined. Additionally, we can pass in any number of variables of any type, in which they don’t have to be of the same time, we also don’t have to pass in any variables at all. In most languages, we are also allowed to return nothing, which is typically done by specifying the return type as void.
For us to use the functions we create we must call them within the parts of our program in which we want to use them.
Calling the function, is done by using the name followed by a set of parenthesis, following on from the example above we would call the function AddNumbers in the following way: AddNumbers(5,3). The values we passed in are stored in the variables a and b respectively and are then added together, return the variable c which will equal 8. In the example just given though we are calling the function but we are not doing anything with the value returned. To make use of the return value c we need to store that data somewhere, like in a variable. To call the function and store the value would look like the following:
Int d = AddNumbers(5,3)
Functions can be called from anywhere in our program, that is we can all them within loops, if statements, or even within other functions. Functions essentially point to a block of instructions that we want to execute so when we call a function you can think that we are just adding that block of instructions into our program at that point.
As you can start to see functions are a powerful concept. They allow us to reuse a set of statements as many times as we want in our program reducing the amount of instructions we need to write. They also allow us to better organise our program, making it easier to maintain, well that is if we design them properly.
When deciding whether to write a function there are a few things worth considering. The first step is to decide whether the instructions you want to put into a function are going to be used more than once, if not then you might not have to put them in one.
Secondly you must decide on the return type. Do you think your function should return anything, and if so, then what? Then finally we need to figure out what parameters if anything we need to pass into the function. The specifics are all dependent on the problem you are trying to solve, or the program you are trying to write.
If we wanted to do any mathematical operations such as adding or subtracting numbers then we can assume that we would want to pass in the numbers we want to add together either as variables or as a data structure. We would also probably want to use the result of the function, and therefore should return it.
If we wanted to output something to the screen and wanted to write that into a function we would mostly likely have a parameter of the thing we want to print: a number, or word, but we would most likely not want to return anything as we simply want to output to the screen.
I think the most important thing to think of when designing functions is to remember that a function should only do one thing. If we want to write a program that adds two numbers together and then prints them out we can see that the there are two things we want to do, add numbers, and print them, and that these tasks are separate from one another, and therefore should end up in two separate functions. If we were write them into a single function, we would never be able to reuse our code as effectively as possible. We wouldn’t be able to add two numbers together without printing them, nor could we print a number without first adding it to another.
On a final note to allow functions to help us organise and improve the readability of our programs it is essential that our functions are given a meaningful name, this stems to our variables as well. We need to know what is being stored in a variable, or what a function we call does, and this is best coming across in the names we select for them.
In this article, we have learnt about functions. A function is a grouping of statements that can be referenced by name, that can accept and return data. Using the name of a function we can call it multiple times in different parts of our program. This results in cleaner, more organised programs, that avoid us having to write duplicate code when wanting to perform a similar task, in which only the data has changed.
After reading this article, and assuming you have been reading the rest of the series, you should have a good understanding of the major concepts that most languages are built around. In the final article in this series, we will look at combining all the concepts we have learn about so far, by introducing algorithms.