A FUNCTION reference is a data type that, instead of simply holding data, contains a link to a specific function in memory.
At first, the concept may be surprising because when you start programming, you get used to having variables with data on one side and functions that manipulate them on the other.
But when we talk about variables, we said that a variable is “a box” that can hold different things. Or as Peter Griffin would say… “a box can hold anything… even a boat!”
Now, this includes containing functions, not just data.
What are the advantages of being able to assign the function to a variable? Now we can treat a function as an object that can be assigned, passed as an argument, returned as a result, or stored in a data structure.
Don’t worry if “you’re finding it hard to grasp”. But it’s a very powerful technique that allows us to separate the implementation of the function from its alias for invoking it, making code reuse easier and promoting modular code creation.
Function References
Let’s translate what we’ve said into some code (don’t worry too much about the syntax, we’ll see concrete examples later. Right now it’s just an excuse to understand each other).
What I meant is that we are usually used to having,
- Variables that hold data like
my_variable
that holds 10 - Functions, like
DoSomething
, that perform actions
That is, something like this,
// a variable with data
const my_variable = 10
// a function
function DoSomething()
{
}
DoSomething() // invoke the function
Now let’s see how to combine both things, a variable that contains a FUNCTION reference to the function. In this case, it would look like this,
// a function
function DoSomething()
{
}
// a variable that contains a function
const my_variable = DoSomething;
my_variable() // invoke a function through the variable
Instead of calling the function by its original name, we can use our FUNCTION reference to invoke it.
Importantly, we need to be careful and differentiate between assigning and invoking the function. For example, in the following case, observe the difference between assigning the function and invoking the function.
// this assigns the function to the variable
var my_variable = DoSomething;
// this invokes the function and assigns the result to the variable
var my_variable = DoSomething();
The way to invoke the function will depend on the language we are using. Generally, it’s ()
. But in any case, the concepts are the same. Next, we’ll see concrete implementation cases in various languages.
Examples of Function References in Different Languages
Let’s look at an example of how to make a reference to a function in different languages. For the example, we will create a function sum
that takes two parameters a
and b
and returns their sum.
Then we’ll create a variable sum_function
that contains a reference to the function. We will then invoke this function through the variable, instead of by its name.
Here’s how this example would look in different programming languages.
C# has the concept of delegate
, which is a system for Function References.
// Definition of the sum function
int Sum(int a, int b)
{
return a + b;
}
void Main(string[] args)
{
// Assigning the function to a delegate
Func<int, int, int> sum_function = Sum;
// Invoking the function through the delegate
Console.WriteLine(sum_function(3, 4)); // Prints: 7
}
In C++ there is the concept of pointer
, which allows establishing Function References.
// Definition of the sum function
int sum(int a, int b) {
return a + b;
}
int main() {
// Assigning the function to a function pointer
int (*sum_function)(int, int) = sum;
// Invoking the function through the pointer
std::cout << sum_function(3, 4) << std::endl; // Prints: 7
}
JavaScript is a dynamically typed language. Of course, it is possible to use variables to hold other functions. In fact, this is very common in this language.
// Definition of the sum function
function sum(a, b) {
return a + b;
}
// Assigning the function to a variable
const sum_function = sum;
// Invoking the function through the variable
console.log(sum_function(3, 4)); // Prints: 7
Finally, Python also supports Function References. In this case, there is no need to declare the variable, just assign the function.
# Definition of the sum function
def sum(a, b):
return a + b
# Assigning the function to a variable
sum_function = sum
# Invoking the function through the variable
print(sum_function(3, 4)) # Prints: 7
As we can see, apart from the syntax differences, the concepts and even the usage are basically identical.
Internal Working Advanced
The operation of function references is implemented differently depending on the programming language. However, broadly speaking, we can provide a common explanation of how they work.
When a function is defined in a programming language, its code is stored in a specific location in memory. This location is identified by a unique memory address.
A function reference is simply a data type that contains this memory address. When we pass a function as a reference to another function or store it in a variable, what we are actually doing is storing this memory address.
When we use a function reference to invoke the referenced function, the program accesses the memory address stored in the reference and executes the code stored at that location.
Moreover, this allows the program to dynamically invoke the referenced function at runtime, providing flexibility and dynamism to the code.
In reality, if you think about it, it’s nothing more than a GO-TO. But supercharged, and much more controlled and safe.