spacer

Webref WebRef   Sitemap · Experts · Tools · Services · Newsletters · About i.com

home / programming / perl / professional /chap7 / 5 To page 1To page 2current pageTo page 4
[previous] [next]

Professional Perl

Developer News
Microsoft Shows Off Silverlight 4, IE9 Plans
Metasploit Expands Vulnerability Test Framework
HyperCard Reborn?

Closures

Closures are subroutines that operate on variables created in the context in which they were defined, rather than passed in or created locally. This means that they manipulate variables outside their own definition, but within their scope. Here is a simple example of a closure at work:

$count = 0;
sub count {return ++ $count;}
print count, count, count;
# print 12

Here the subroutine count uses the variable $count. But the variable is defined outside of the subroutine, and so is defined for as long as the program runs. Nothing particularly remarkable so far, all we are doing is defining a global variable. However, what makes closures useful is that they can be used to implement a form of memory in subroutines where the variable is global inside the subroutine, but is invisible outside. Consider the following example:

{
$count = 0;
   sub count {return ++ $count;}
}
print count, count, count;

# still print 12

What makes this interesting is that the variable $count is no longer directly accessible by the time we get to the print statement. Ordinarily it would have ceased to exist at the end of the block in which it is defined because it is lexical, and therefore bounded by the block's scope. However, it is referred to in the subroutine count, which is by nature a global definition. Consequently, Perl still has a reference to the variable and so it persists. The only place the reference exists is in the subroutine count, so we have effectively created a persistent and private variable inside count.

Closures get more interesting when we create them in an anonymous subroutine. If we replace the block with a subroutine definition and count with an anonymous subroutine, we end up with this:

sub make_counter ($) {
   $count = shift;
   return sub {return $count++;}
}

The outer subroutine make_counter accepts one scalar variable and uses it to initialize the counter variable. We then create an anonymous subroutine that refers to the variable (thus preserving it) and returns the code reference of the anonymous subroutine. We can now use make_counter to create and use any number of persistent counters, each using its own secret counter variable:

$tick1 = make_counter(0);   #counts from zero
$tick2 = make_counter(100);   #counts from 10
$, = ",";
print &$tick1, &$tick2, &$tick1, &$tick2;

# displays 0, 100, 1, 10

Just because the subroutine is anonymous does not mean that it cannot accept parameters - we just access the @_ array as normal. Here is a variation of make_counter that allows us to reset the counter variable by passing a number to the anonymous subroutine:

#!/usr/bin/perl
# closure.pl
use warnings;
use strict;

sub make_counter ($) {
   my $count = @_?shift:0;

   return sub {
      $count = $_[0] if @_;
      return $count++;
   }
}

my $counter = make_counter(0);
foreach (1..10) {
   print &$counter, "\n";
}
print "\n";   # displays 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

$counter -> (1000);   #reset the counter
foreach (1..3) {
   print &$counter, "\n";
}
print "\n";
# displays 1000, 1001, 100

Closures also provide a way to define objects so that their properties cannot be accessed from anywhere other than the object's own methods. The trick is to define the object's underlying data in terms of an anonymous subroutine that has access to an otherwise inaccessible hash, in the same way that the variable $count is hidden here. We will take a look at doing this in Chapter 18, along with tied objects, which would allow us to disguise a counter like the one above as a read-only scalar variable that increments each time we access it.

home / programming / perl / professional /chap7 / 5 To page 1To page 2current pageTo page 4
[previous] [next]

internet.commediabistro.comJusttechjobs.comGraphics.com

Search:

WebMediaBrands Corporate Info

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | Shopping | E-mail Offers | Freelance Jobs

webref The latest from WebReference.com Browse >
Rolling Out Your Own HTML Application Version Control · HTML 5: Client-side Storage · Working with Ajax Server Extensions
Sitemap · Experts · Tools · Services · Email a Colleague · Contact FREE Newsletters 
 The latest from internet.com
Wi-Fi Product Watch, November 2009 · Chip Market Recovering From '08 Collapse · Low-Cost Tools to Kickstart Your New Business


Created: April 18, 2001
Revised: April 18, 2001


URL: http://webreference.com/programming/perl/professional/chap7/5/