- Subroutines
- Retrieving arguments to a subroutine with shift
- Assign arguments to a subroutine with list assignment
- Handle arguments directly by accessing @_
- Arguments passed can get modified
- Subroutines have no argument checking
- Perl has "prototypes". Ignore them.
- Make things happen at compile time with the BEGIN block
- Pass in arrays and hashes as references
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 @
.
- sub volume {
- my $height = shift;
- my $width = shift;
- my $depth = shift;
- return $height * $width * $depth;
- }
Assign arguments to a subroutine with list assignment
You can also assign arguments en masse with list assignment:
- sub volume {
- my ($height, $width, $depth) = @_;
- return $height * $width * $depth;
- }
Handle arguments directly by accessing @_
In some cases, but we hope very few, you can access arguments directly in the @_
array.
- sub volume {
- return $_[0] * $_[1] * $_[2];
- }
Arguments passed can get modified
The arguments passed to a subroutine are aliases to the real arguments.
- my $foo = 3;
- print incr1($foo) . "\n"; # prints 4
- print "$foo\n"; # prints 3
- sub incr1 {
- return $_[0]+1;
- }
This can be good if you want it to be:
- sub incr2 {
- return ++$_[0];
- }
Subroutines have no argument checking
You can pass any anything to a subroutine that you want.
- sub square {
- my $number = shift;
- return $number * $number;
- }
- 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:
- 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:
- sub square($) {
- ...
- }
- 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:
- use WWW::Mechanize;
- BEGIN {
- require WWW::Mechanize;
- import WWW::Mechanize;
- }
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:
- my @stooges = qw( Moe Larry Curly );
- my @sandwiches = qw( tuna ham-n-cheese PBJ );
- lunch( @stooges, @sandwiches );
Then what's passed in to lunch
is the list
- ( "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:
- sub lunch {
- my (@stooges, @sandwiches) = @_;
then all six elements go into @stooges
and @sandwiches
gets nothing.
The answer is to use references, as in:
- lunch( \@stooges, \@sandwiches );
- sub lunch {
- my $stoogeref = shift;
- my $sandwichref = shift;
- my @stooges = @{$stoogeref};
- my @sandwichref = @{$sandwichref};
- ...
- }
Want to contribute?
Submit a PR to github.com/petdance/perl101