Open In App

Perl – Closure Function

Improve
Improve
Like Article
Like
Save
Share
Report

Closure is one of the important concepts in Perl. Closure is a computer term with an accurate but a hard to explain meaning. It is often referred as a function that can be stored as a variable, which has a special ability to access other variables local to the scope it was created in. It is used to refer to any of the outer function’s local variable and when the compiler detects that, it moves these variables to the closure’s hidden object declaration from the outer function’s stack space. It then generates a variable of closure type.
So basically, a function that captures the lexical environment in which it is created – i.e it runs around collecting all the things in the environment at that time is known as a closure function.

Closure with respect to the Perl language means that: subroutine 1 returns some other subroutine 2, then subroutine 2 accesses the variable x present in subroutine 1 and when the execution of the subroutine 1 ends, the user can no longer access x, but the subroutine 2 because also refers to the variable x point to the data object. It makes subroutine 2 continue to access this data object after the end of subroutine 1.
Therefore, the variable x in subroutine 1 must be a lexical variable, otherwise, after the execution of subroutine 1, the variable x may still be accessed by the outside world, modify, if so, the closure and the normal function is meaningless.

A closure is a type of function that is bound to a certain environment and is written as a function inside of another function.

Example:




sub make_adder 
{
    my $addpiece = shift;
    return sub { shift() + $addpiece };
}
  
# Driver Code
my $f1 = make_adder(555);
my $f2 = make_adder(20);


Now $f1($n) is always 555 plus whatever $n you pass in, whereas $f2($n) is always 20 plus whatever $n you pass in. The $addpiece in the closure sticks around.

Uses of Closures

Closures are really useful things. For example for callbacks, instead of passing a callback function pointer + argument in a function, and having to work out in that function what you’ve been called back with, one can just use a closure. When that function is called, it has access to all the lexical environment of when it was created.

Some of the main uses of closure are: Using them as ‘smart’ callback and the other one is using them as Iterators.

  • Smart callback function
    For example: We want to create a button (using the Tk toolkit) giving it a subroutine reference. But it will be a problem if we want to give a subroutine to 2 different buttons on the screen. Therefore to do that, we’ll use a ‘smart’ callback routine i.e a closure. This will make the closure store some data which is specific to that button (like its name) and when that subroutine is called, it gives it the access to that data.
  • Iterators
    An iterator is usually a code reference that, when executed, it calculates the next item in a list and returns it.
    For example: Consider there is a stream of even numbers and has an iterator on it which returns the next even number whenever it is called. Clearly it’s not possible to generate all possible even numbers, but it can always compute the next even number if it remembers the previous number generated. This piece of crucial information is remembered by the iterator.
  • Another use of closure is that it can make a variable private to a named subroutine.
    For example: A counter which gets initialized at the creation time of the sub and can only be modified from within the sub. This can be used sometimes with a BEGIN block in package files to make sure that a variable doesn’t interfere with during the lifetime of the package.

Use of Partial Application

The partial application function is known as the ability to take a function having many parameters and apply arguments to some of those parameters to create a new function that requires application of only the remaining arguments to produce the equivalent of applying the arguments to the original function.
The recurring feature of partial application is that when it is applied to a parameter, other parameters are not supposed to be mentioned explicitly.

Example:




sub fs(&) 
    my $func = shift;
    sub { map $func->($_), @_ }
}
    
sub double($) { shift() * 2 }
sub square($) { shift() ** 2 }
    
my $fs_square = fs(\&square);
my $fs_double = fs(\&double);
    
my @s = 0 .. 3;
print "fs_square(@s): @{[ $fs_square->(@s) ]}\n";
print "fs_double(@s): @{[ $fs_double->(@s) ]}\n";
    
@s = (2, 4, 6, 8);
print "fs_square(@s): @{[ $fs_square->(@s) ]}\n";
print "fs_double(@s): @{[ $fs_double->(@s) ]}\n";


Output:

fs_square(0 1 2 3): 0 1 4 9
fs_double(0 1 2 3): 0 2 4 6
fs_square(2 4 6 8): 4 16 36 64
fs_double(2 4 6 8): 4 8 12 16


Last Updated : 02 Jul, 2020
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads