What is a Closure in computer programming?
To understand the concept of closure, we need to know the differences between the static scope and dynamic scope. Besides, we need to know what is a Lambda function also. These terms are the preconditions to dive into the Closure term.
Static or Lexical vs. Dynamic scoping
In programming we divide scoping into two classes:
- Static Scoping
- In Static scoping or lexical scoping a variable always refers to its top-level environment. This is a property of the program text and unrelated to the run-time call stack. Static scoping also makes it much easier to make a modular code. A programmer can figure out the scope just by looking at the code.
// A C program to demonstrate static scoping.
#include<stdio.h>
int x = 10;
// Called by g()
int f()
{
return x;
}
// g() has its own variable
// named as x and calls f()
int g()
{
int x = 20;
return f();
}
int main()
{
printf("%d", g());
printf("\n");
return 0;
}
// Output
10
- Dynamic Scoping
- With dynamic scope, a global identifier refers to the identifier associated with the most recent environment and is uncommon in modern languages. In technical terms, this means that each identifier has a global stack of bindings and the occurrence of an identifier is searched in the most recent binding.
// Since dynamic scoping is very uncommon in
// the familiar languages, we consider the
// following pseudo code as our example. It
// prints 20 in a language that uses dynamic
// scoping.
int x = 10;
// Called by g()
int f()
{
return x;
}
// g() has its own variable
// named as x and calls f()
int g()
{
int x = 20;
return f();
}
main()
{
printf(g());
}
// Output
20
So what is a Lambda function?
Because the function has no name, you can’t use it as a regular function. Instead, you must either assign it to a variable or pass it to another function as an argument. So Lambda is an anonymous function.
// Anonymous function assigned to variable
$greeting = function () {
return "Hello world";
}
// Call function
echo $greeting();
// Returns "Hello world"
What is a Closure then?
A Closure is essentially the same as a Lambda, apart from it can access variables outside the scope of the closure. The most understandable definition for closure would be this:
“Closure is when a function “remembers” its lexical scope even when the function is executed outside that lexical scope”.
// Create a user
$user = "Philip";
// Create a Closure
$greeting = function() use ($user) {
echo "Hello $user";
};
// Greet the user
$greeting(); // Returns "Hello Philip"
As you can see above, the Closure is able to access the $user variable. because it was declared in the use clause of the Closure function definition.
Closures are useful when you want to make more complicated synchronous operations by containing an external state within an inner function expression.
If you were to alter the $user variable within the Closure, it would not affect the original variable. To update the original variable, we can append an ampersand. An ampersand before a variable means this is a reference and so the original variable is also updated.
// Set counter
$i = 0;
// Increase counter within the scope
// of the function
$closure = function () use ($i){ $i++; };
// Run the function
$closure();
// The global count hasn’t changed
echo $i; // Returns 0
// Reset count
$i = 0;
// Increase counter within the scope
// of the function but pass it as a reference
$closure = function () use (&$i){ $i++; };
// Run the function
$closure();
// The global count has increased
echo $i; // Returns 1
Closures are also useful when using PHP functions that accept a callback function like array_map, array_filter, array_reduce, or array_walk.
The array_walk function takes an array and runs it through the callback function.
// An array of names
$users = array("John", "Jane", "Sally", "Philip");
// Pass the array to array_walk
array_walk($users, function ($name) {
echo "Hello $name<br>";
});
// Returns
// -> Hello John
// -> Hello Jane
// -> ..
Conclusion and Closing
In this post, I have tried to clarify what is Lambda and what is Closure. To summarize this in a topic, let’s check the following example:
function ($quantity, $product) use ($tax, &$total)
With closures, to access variables that are outside of the context of the function you need to explicitly grant permission to the function using the use function. What it means, in this case, is that you’re granting the function access to the $tax and $total variables.
Another thing to point out is that $tax is passed as a copy while $total is passed by reference (by appending the & sign in front). Passing by reference allows the closure to modify the value of the variable. Any changes to the value of $tax, in this case, will only be effective within the closure while the real value of $total will change outside as well.