Äîęóěĺíňŕöč˙
HTML CSS PHP PERL äđóăîĺ

Creating and Calling Subroutines

 
Previous Table of Contents Next

Creating and Calling Subroutines

You create user-defined subroutines in Perl by using the following syntax:


sub subroutine_name {

    statement1;

    :

    statementx;

}


Subroutine names in Perl follow the same naming conventions as scalars, arrays, and hashes outlined in Hour 2, "Perl's Building Blocks: Numbers and Strings." Subroutine names can have the same names as existing variables. However, you should avoid creating subroutine names that are the same as those of Perl's built-in functions and operators. Creating two subroutines with the same name in Perl causes Perl to emit a warning if warnings are enabled; otherwise, the second definition causes the first to be forgotten.

Here is an example of a subroutine:


sub  countdown {

    for ($i=10; $i>=0; $i--) {

        print "$i -";

    }

}


When the program needs to use the code in the subroutine, you can use either of the following syntax lines to call (or invoke) the subroutine:


&countdown();


or


countdown();


You can use the second syntax (without the &) if the subroutine has been declared in the code already, although the &countdown() syntax is acceptable anywhere, and some consider it more readable. In this book, I'll declare subroutines ahead of where they're first called, and I'll use the form without the &, although either is acceptable.

When the subroutine is invoked, Perl remembers where it was, executes the subroutine's code, and then returns to the remembered place in the program when the subroutine is complete, as in the following example:


print "T-minus: ";

countdown();

print "Blastoff!\n";


prints


T-minus: 10 -9 -8 -7 -6 -5 -4 -3 -2 -1 -0 -Blastoff!


Perl subroutines can be called anywhere within your program, including within other subroutines, as shown here:


sub world {

    print "World!";

}

sub hello {

    print "Hello, ";

    world();

}

hello();


Returning Values from Subroutines

A subroutine isn't just for grouping code together by a convenient name. A subroutine, like Perl's functions, operators, and expressions, also has a value, called the subroutine's return value. The return value of a subroutine is the value of the last expression evaluated in the subroutine or a value explicitly returned by the return statement.

The return value of the subroutine, computed when the subroutine is called, can then be used in whatever code called the subroutine. Consider the following example:


sub two_by_four {     # A silly subroutine

    2 * 4;

}

print 8*two_by_four();


In the preceding snippet, for Perl to evaluate the expression 8*two_by_four(), the subroutine two_by_four() is run and the value 8 returned. The expression 8*8 is then evaluated, and 64 is printed.

Values can also be explicitly returned from a subroutine with the return statement. Use a return statement when your program needs to return before the end of the subroutine or when you want to be explicit about what value is being returned—instead of just "falling off" the end of the subroutine and using the last expression's value. The following snippet uses both methods:


sub x_greaterthan100 {

    # Relies on the value of $x being set elsewhere

    return(1) if ( $x > 100 );

    0;

}

$x = 70;

if (x_greaterthan100()) {

    print "$x is greater than 100\n";

}


Subroutines can return arrays and hashes as well as scalars, as shown here:


sub shift_to_uppercase {

    @words = qw( cia fbi un nato unicef );

    foreach (@words) {

       $_ = uc($_);

    }

    return (@words);

}

@acronyms=shift_to_uppercase();


Arguments

All the preceding examples of subroutines have one thing in common: They act on either data that was hard-coded (2*4) or variables that just happened to have the right data in them ($x for x_greaterthan100()). This limitation creates a problem because functions that rely on hard-coded data or expect variables to be set outside the function aren't really portable. It would be nice to call a function and say, "Take this data and do something with it," and then call it later and say, "Take this other data and do something with it." The result of calling a function, then, can change depending on what is passed to it.

These values given to functions to change their results are called arguments, and you've been using them throughout this book. Perl's built-in functions (grep, sort, reverse, print, and so on) take arguments, and now yours can too. To pass a subroutine arguments, you can use any of the following:


subname(arg1, arg2, arg3);

subname arg1, arg2, arg3;

&subname(arg1, arg2, arg3);


You can use the second form—without the parentheses—only if Perl has encountered the subroutine definition already.

In a subroutine, any arguments that were passed to it are accessible through the Perl special variable @_. This snippet demonstrates passing arguments—the three string literals—and printing them with a function:


sub printargs {

    print join(',', @_);

}

printargs('market', 'home', 'roast beef');


To access individual arguments that were passed in, as shown in the following example, you use an index on the array @_ as you would any other array. Just remember that $_[0]—an element of @_—has nothing to do with the scalar variable $_.


sub print_third_argument {

    print $_[2];

}


Working with variable names like $_[3] isn't exactly a "clear" style of programming. Functions that take multiple arguments often begin by giving names to those arguments; this practice makes it clearer what they do. To see what I mean, check out the following example:


sub display_box_score {

    ($num_hits, $num_at_bats)=@_;

    print "For $num_at_bats trips to the plate, ";

    print "he's hitting ", $num_hits/$num_at_bats, "\n";

}

display_box_score(50, 210);


In the preceding subroutine, the array @_ is copied to the list ($num_hits, $num_at_bats). The first element of @_$_[0]—becomes $num_hits, and the second $num_at_bats. The variable names are simply used here for readability.

By the Way

The variable @_ actually contains aliases to the original arguments that were passed to the subroutine. Modifying @_ (or any element of @_) modifies the original variables in the argument list. Doing so unexpectedly is considered bad form; your function shouldn't interfere with arguments from callers to the function unless the users of the function are expecting this.


Passing Arrays and Hashes

Arguments to subroutines don't have to be scalars. You can pass arrays and hashes to subroutines, but doing so requires some thought. You pass an array—or hash—to a subroutine the same way you pass a scalar:


@sorted_items=sort_numerically(@items);


In the subroutine, the entire array @items is referenced through @_:


sub sort_numerically {

    print "Sorting...";

    return( sort { $a <=> $b} @_);

}


You do hit a small snag when passing hashes and arrays to subroutines: Passing two or more hashes (or arrays) to a subroutine doesn't usually do what you want. Examine this snippet of code:


sub display_arrays {

    (@a, @b) = @_;

    print "The first array: @a\n";

    print "The second array: @b\n";

}

display_arrays(@first, @second);


The two arrays @first and @second are put into a list together, and the elements are put into @_ during the subroutine call. The end of the @first's elements are indistinguishable from the beginning of @second's elements in @_; it's just one large flat list. Inside the subroutine, the assignment (@a, @b)=@_ takes all the elements in @_ and assigns them to @a. The array @b gets no elements. (The reason for this was explained in Hour 4, "Stacking Building Blocks: Lists and Arrays.")

One or more scalars can be passed along with a single array or hash, as long as the scalars are passed first in the argument list and you know how many you have. That way, the hash or array encompasses all the values beyond the last scalar, as in this example:


sub lots_of_args {

    ($first, $second, $third, %hash) = @_;

    # rest of subroutine...

}

lots_of_args($foo, $bar, $baz, %myhash);


If you must pass multiple arrays and hashes into a subroutine (and be able to distinguish them later), you must use references. You'll learn how to pass references in Hour 13, "References and Structures."

    Previous Table of Contents Next
    © 2000- NIV