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
Subroutine References
PERL --- 08/16/2001

Andrew Johnson

We have used subroutine references a couple of times in previous articles, but we haven't looked at them directly. You can take a reference to an existing (named) subroutine using the backslash operator along the ampersand in the following manner: 

On this topic

sub foo {
print "This is foo\n"; }

my $sref = \&foo;

You can call the referenced routine by preceding the scalar holding it with an ampersand, or by using the dereference arrow and parentheses:

&$sref; # or: &$sref('argument')
$sref->(); # or: $sref->('argument')

It is important to realize that you cannot take a reference to a subroutine and pass it arguments at the same time:

my $sref = \&foo('argument');

What this actually does is return a reference to the return value of that function (using the given argument), which probably isn't what you wanted.

But what are subroutine references good for? A couple of common uses are dispatch tables and passing routines as arguments to other routines; we will consider the first here. A dispatch table is simply a table (usually a hash) that allows you to select the routine to run. Consider a user interface that queries the user to enter a command to run:

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

sub this { print "You picked 'this'\n" }
sub that { print "You picked 'that'\n" } sub quit { exit }

print "Enter a command:\n";
while (<STDIN>) { chomp(my $cmd = $_); if ($cmd eq 'this') { this(); } elsif ($cmd eq 'that') { that(); } elsif ($cmd eq 'quit' or $cmd eq 'exit') { quit(); } else { print "Unrecognized command: $cmd\n"; } } __END__

Now imagine that there are many more possible commands the user could enter and you can see that the program would grow quite large. Using a dispatch table simplifies all of the logic of the if/elsif statements into the data structure:

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

sub this { print "You picked 'this'\n" }
sub that { print "You picked 'that'\n" } sub quit { exit }

my %dispatch = (
this => \&this, that => \&that, quit => \&quit, exit => \&quit, );

print "Enter a command:\n";
while (<STDIN>) { chomp(my $cmd = $_); if ($dispatch{$cmd}) { $dispatch{$cmd}->(); } else { print "Unrecognized command: $cmd\n"; } } __END__

This program is actually a little longer, but it is simpler in design and simpler to maintain and update; adding new commands involves only defining a subroutine and adding another entry to the hash (we don't have to add further elsif clauses as we would with the first example.

Next Week: Passing subroutine references

 

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



Advertisements
Sponsored links
Locate Hidden Software on business PCs with this free tool
KODAK i1400 Series Scanners stand up to the challenge
Top 5 Reasons to Combine App Performance and Security
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.