Subroutines

Retrieving arguments to a subroutine with shift

A subroutine's arguments come in via the special @ array.The shift without an argument defaults to @.

  1. sub volume {
  2. my $height = shift;
  3. my $width = shift;
  4. my $depth = shift;
  5.  
  6. return $height * $width * $depth;
  7. }

Assign arguments to a subroutine with list assignment

You can also assign arguments en masse with list assignment:

  1. sub volume {
  2. my ($height, $width, $depth) = @_;
  3.  
  4. return $height * $width * $depth;
  5. }

Handle arguments directly by accessing @_

In some cases, but we hope very few, you can access arguments directly in the @_ array.

  1. sub volume {
  2. return $_[0] * $_[1] * $_[2];
  3. }

Arguments passed can get modified

The arguments passed to a subroutine are aliases to the real arguments.

  1. my $foo = 3;
  2. print incr1($foo) . "\n"; # prints 4
  3. print "$foo\n"; # prints 3
  4.  
  5. sub incr1 {
  6. return $_[0]+1;
  7. }

This can be good if you want it to be:

  1. sub incr2 {
  2. return ++$_[0];
  3. }

Subroutines have no argument checking

You can pass any anything to a subroutine that you want.

  1. sub square {
  2. my $number = shift;
  3.  
  4. return $number * $number;
  5. }
  6.  
  7. my $n = square( 'Dog food', 14.5, 'Blah blah blah' );

Only the first argument is used by the function. For that matter, you can call the function with any number of arguments, even no arguments:

  1. my $n = square();

and Perl won't complain.

The module Params::Validate solves many of these validation problems.

Perl has "prototypes". Ignore them.

Somewhere along the way, prototypes got added, so you can do things like this:

  1. sub square($) {
  2. ...
  3. }
  4.  
  5. my $n = square( 1, 2, 3 ); # run-time error

However, don't use them. They don't work on objects, and they require that the subroutines be declared before they're called. They're a nice idea, but just not practical.

Make things happen at compile time with the BEGIN block

BEGIN is a special type of code block. It allows programmers to execute code during Perl's compile phase, allowing for initializations and other things to happen.

Perl uses BEGIN any time you use a module; the following two statements are equivalent:

  1. use WWW::Mechanize;
  2.  
  3. BEGIN {
  4. require WWW::Mechanize;
  5. import WWW::Mechanize;
  6. }

Pass in arrays and hashes as references

Remember that the parameters passed into a subroutine are passed as one big array. If you do something like the following:

  1. my @stooges = qw( Moe Larry Curly );
  2. my @sandwiches = qw( tuna ham-n-cheese PBJ );
  3.  
  4. lunch( @stooges, @sandwiches );

Then what's passed in to lunch is the list

  1. ( "Moe", "Larry", "Curly", "tuna", "ham-n-cheese", "PBJ" );

Inside lunch, how can you tell where the stooges end and the sandwiches begin? You can't. If you try this:

  1. sub lunch {
  2. my (@stooges, @sandwiches) = @_;

then all six elements go into @stooges and @sandwiches gets nothing.

The answer is to use references, as in:

  1. lunch( \@stooges, \@sandwiches );
  2.  
  3. sub lunch {
  4. my $stoogeref = shift;
  5. my $sandwichref = shift;
  6.  
  7. my @stooges = @{$stoogeref};
  8. my @sandwichref = @{$sandwichref};
  9. ...
  10. }

Want to contribute?

Submit a PR to github.com/petdance/perl101