A.18 Subroutines

Subroutines are defined by the keyword sub, followed by the name of the subroutine, followed by a block enclosed by curly braces containing the body of the subroutine. The following is a simple example.

sub a_subroutine {
    print "I'm in a subroutine\n";
}

In general, you can call subroutines using the name of the subroutine followed by a parenthesized list of arguments:

a_subroutine();

Arguments can be passed into subroutines as a list of scalars. If any arrays are given as arguments, their elements are interpolated into the list of scalars. The subroutine receives all scalar values as a list in the special variable @_. This example illustrates a subroutine definition and the calling of the subroutine with some arguments:

sub concatenate_dna {
    my($dna1, $dna2) = @_;

    my($concatenation);

    $concatenation = "$dna1$dna2";

    return $concatenation;
}

print concatenate_dna('AAA', 'CGC');

This prints:

AAACGC

The arguments 'AAA' and 'CGC' are passed into the subroutine as a list of scalars. The first statement in the subroutine's block:

 my($dna1, $dna2) = @_;

assigns this list, available in the special variable @_, to the variables $dna1 and $dna2.

The variables $dna1 and $dna2 are declared as my variables to keep them local to the subroutine's block. In general, you declare all variables as my variables; this can be enforced by adding the statement use strict; near the beginning of your program. However, it is possible to use global variables that are not declared with my, which can be used anywhere in a program, including within subroutines.

The statement:

 my($concatenation);

declares another variable for use by the subroutine.

After the statement:

$concatenation = "$dna1$dna2";

performs the work of the subroutine, the subroutine defines its value with the return statement:

 return $concatenation;

The value returned from a call to a subroutine can be used however you wish; in this example, it is given as the argument to the print function.

If any arrays are given as arguments, their elements are interpolated into the @_ list, as in the following example:

sub example_sub {
    my(@arguments) = @_;

    print "@arguments\n";
}

my @array = (`two', `three', `four');

example_sub(`one', @array, `five');

This prints:

one two three four five

Note that the following attempt to mix arrays and scalars in the arguments to a subroutine won't work:

# This won't work!!
sub bad_sub {
    my(@array, $scalar) = @_;

    print $scalar;
}

my @arr = ('DNA', 'RNA');
my $string = 'Protein';

bad_sub(@arr, $string);

In this example, the subroutine's variable @array on the left side in the assignment statement consumes the entire list on the right side in @_, namely ('DNA', 'RNA', 'Protein'). The subroutine's variable $scalar won't be set, so the subroutine won't print 'Protein' as intended. To pass separate arrays and hashes to a subroutine, you need to use references. Here's a brief example:

sub good_sub {
    my($arrayref, $hashref) = @_;

    print "@$arrayref", "\n";

    my @keys = keys %$hashref;

    print "@keys", "\n";
}

my @arr = ('DNA', 'RNA');
my %nums = ( 'one' => 1, 'two' => 2);

good_sub(\@arr, \%nums);

This prints:

DNA RNA
one two