spacer

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

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

Professional Perl

Developer News
Mandrake Linux Founder Back, Virtually
Amazon: We're a Technology Company
Sun Expands MySQL With Closed Source

Passing Lists and Hashes

We mentioned earlier, when we started on the subject of passed arguments, that passing lists and hashes directly into a subroutine causes list flattening to occur, just as it does with ordinary list definitions. Consequently, if we want to pass an array or hash to a subroutine, and keep it intact and separate from the other arguments, we need to take additional steps. Consider the following snippet of code:

$message = "Testing";
@count = (1, 2, 3);
testing ($message, @count);   # calls 'testing' -- see below

The array @count is flattened with $message in the @_ array created as a result of this subroutine, so as far as the subroutine is concerned the following call is actually identical:

testing ("Testing", 1, 2, 3);

In many cases this is exactly what we need. To read the subroutine parameters we can just extract the first scalar variable as the message and put everything else into the count:

sub testing {
   ($message, @count) = @_;
   ...
}

Or, using shift:

sub testing {
   $message = shift;
   # now we can use @_ directly in place of @count
   ...
}

The same principle works for hashes, which as far as the subroutine is concerned is just more values. It is up to the subroutine to pick up the contents of @_ and convert them back into a hash:

sub testing {
   ($message, %count) = @_;
   print "@_";
}

testing ("Magpies", 1 => "for sorrow", 2 => "for joy", 3 => "for health", 4 => "for wealth", 5 => "for sickness", 6 => "for death");

However, this only works because the last parameter we extract inside the subroutine absorbs all the remaining passed parameters. If we were to write the subroutine to pass the list first and then the scalar afterwards, all the parameters are absorbed into the list and the scalar is left undefined:

sub testing {
   (@count, $message) = @_;   # ERROR
   print "@_";
}	

testing(1, 2, 3, "Testing");
# results in @count = (1, 2, 3, "Testing") and $message = undef

If we can define all our subroutines like this we won't have anything to worry about, but if we want to pass more than one list we still have a problem. If we attempt to pass both lists as-is, then extract them inside the subroutine, we end up with both lists into the first and the second left undefined:

sub testing {
   my (@messages, @count) = @_; # wrong!
   print "@_";
}

@msgs = ("Testing", "Testing");
@count = (1, 2, 3);
testing(@msgs, @count);
# results in @messages = ("Testing", "Testing", "Testing", 1, 2, 3) and
# @count = ();

The correct way to pass lists and hashes, and keep them intact and separate, is to pass references. Since a reference is a scalar, it is not flattened like the original value and so our data remains intact in the form that we originally supplied it:

testing (["Testing", "Testing"], [1, 2, 3]);   # with two lists
testing (\@messages, \@count);   # with two array variables
testing ($aref1, $aref2);   # with two list references

Inside the subroutine we then extract the two list references into scalar variables and dereference them using either @{$aref} or $aref->[index] to access the list values:

sub testing {
   ($messages, $count) = @_;
   # print the testing messages
      foreach (@ {$messages}) {
      print "$_ ... ";
   }
   print "\n";
   # print the count; 
   foreach (@ {$count}) {
      print "$_! \n";
   }
}

Another benefit of this technique is efficiency; it is better to pass two scalar variables (the references) than it is to pass the original lists. The lists may contain values that are large both in size and number. Since Perl must store a local copy of the @_ array for every new subroutine call in the calling stack, passing references instead of large lists can save Perl a lot of time and memory.

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

Copyright 1999 Wrox Press Ltd. and

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info

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

webref The latest from WebReference.com Browse >
Working with the DOM Stylesheets Collection · Administering RBAC in PHP 5 CMS Framework · xref: Automatic Cross Referencing Script
Sitemap · Experts · Tools · Services · Email a Colleague · Contact FREE Newsletters 
 The latest from internet.com
Combine BottomCount() with Other MDX Functions to Add Sophistication · Creating a Daemon with Python · The Coming Voice-over-WiMAX Revolution


Revised: March 22, 2001
Created: March 22, 2001


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