ITworld.com
  Search  
ITworld Home Page ITworld Webcasts ITworld White Papers ITworld Newsletters ITworld News ITworld Topics Careers ITworld Voices ITwhirled Changing the way you view IT
Closures, Part 1: Subroutine References as Closures
PERL --- 08/30/2001

Andrew Johnson

A closure is a tricky kind of thing to explain, but not terribly hard to understand. The following may not meet with computer science approval as an explanation of closures, but the examples should provide enough hands-on exposure to grasp the underlying concept. 

On this topic

First, you must understand that named subroutines are global by nature; that is, the subroutine name (identifier) lives in the package's symbol table. However, they run within the lexical scope they were defined within.

#!/usr/bin/perl -w
use strict;

{
my $inc = 10; sub incr { print "$inc\n"; $inc++; } }

incr();
incr(); __END__

prints:
10 11

In the above example, $inc is lexically scoped within the block, and the subroutine (incr()) is defined within the same block. We cannot refer to $inc after the block (scope) is finished but we can call the subroutine, which runs within its defined scope so it can still access and change $inc. A closure is simply an anonymous subroutine bound to the lexical scope it was defined within (rather like the above situation).

#!/usr/bin/perl -w
use strict;

sub make_incr {
my $inc = shift; return sub {print "$inc\n"; $inc++}; }

my $c1 = make_incr(10);
my $c2 = make_incr(20);

$c1->();
$c2->(); $c1->(); $c2->(); __END__ prints: 10 20 11 21

Our make_incr() routine is a closure generator. It takes an argument and creates a new lexical variable, then it returns an anonymous subroutine that uses this same variable. Each time we call this routine, a new lexical $inc is created and the anonymous subroutine refers to that particular copy of $inc. Each closure generated ($c1 and $c2) works with their own private copies of $inc. Essentially, they each can save information about their current state (in this case, what number they are currently at).

Here is another simple example (adapted from my book) where the closure itself also takes an argument:

sub exclaim {
my $prefix = shift; return sub {print "$prefix $_[0]!\n"}; }

my $batman = exclaim('Indeed');
my $robin = exclaim('Holy');

$robin->('Mackerel'); # prints: Holy Mackerel! $batman->('Robin'); # prints: Indeed Robin!

Closures can be useful for creating callback routines and iterators. The above example of make_incr() creates very simple iterators that simply count up by ones from a given base number. However, you can create an iterator to iterate through more complex functions as well. Next week we will discuss using a closure as an iterator over the Fibonacci numbers.

Next Week: Closures, Part 2: Iterating Over the Fibonacci Numbers

 

Andrew Johnson works as a programmer/consultant and is the author of Elements of Programming with Perl from Manning Publications.



Advertisements
Sponsored links
Top 5 Reasons to Combine App Performance and Security
KODAK i1400 Series Scanners stand up to the challenge
Locate Hidden Software on business PCs with this free tool
Bring harmony to your mix of UNIX-Linux-Windows computing environments
 Home   Newsletters  PERL
www.itworld.com    open.itworld.com     security.itworld.com     smallbusiness.itworld.com
storage.itworld.com     utilitycomputing.itworld.com     wireless.itworld.com

 
Contact Us   About Us   Privacy Policy    Terms of Service   Reprints  

CIO   Computerworld   CSO   GamePro   Games.net   Industry Standard   Infoworld   ITworld  
JavaWorld   LinuxWorld  MacUser   Macworld   Network World   PC World   Playlist  

DEMO   IDG Connect   IDG Knowledge Hub   IDG TechNetwork   IDG World Expo  

Copyright © Computerworld, Inc. All rights reserved

Reproduction in whole or in part in any form or medium without express written permission of Computerworld Inc. is prohibited. Computerworld and Computerworld.com and the respective logos are trademarks of International Data Group Inc.