This week we will be covering closures. Closures are another basic concept of functional programming. They are based right on top of anonymous functions so if you haven’t read last week’s article it would behoove you to do so.
Closures are subroutines that “close over” variables thereby storing them in the scope of the subroutine to be accessed later. Values stored in variables that exist within the scope of a function are guaranteed to exist as long as the function does. This allows a developer to create subroutines that do many useful things, including provide state and encapsulate values.
In Perl a subroutine can access variables defined anywhere lexically above it, even once the scope that it is in is left. This allows us to access otherwise lost data.
Whereas if we change this example to simply:
This code will fail at compilation time because $value isn’t defined in the outer scope.
This is not unique to named functions, anonymous functions provide the same functionality:
We can use closures to create new subroutines that have some state stored in them. For example, here is a subroutine that returns a subroutine that takes numbers to the power of the variable that was closed over.
It is important to note in the example above that each time power_of_generator is called the new anonymous subroutine returned has a new value to $power and cannot interfere with any other subroutines value of $power.
Another useful ability that closures have is that they can safely encapsulate data, more safely than many of the OOP approaches in Perl.
It is important to note in the example above that $name cannot be accessed outside of the scope of the outer curly brackets. As such, there is no way to set $name to a value that is not title cased. This is because the only way to set name is through set_name() which will not accept a value that isn’t title cased.
The example above only provides the ability to store one name in a running program. If we wanted to safely store multiple names we could do so by wrapping the $name and accompanying subs into a larger sub.
This concludes our discussion on closures. Next week we will move on to currying and a discussion on ‘higher order’ subroutines.