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 with the same names as 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.

When the subroutine is invoked, the subroutine's code is run and any return value is passed back to the place where the subroutine was invoked. (Invoking subroutines and return values is discussed momentarily.) For example, this short subroutine prompts the user for an answer:

sub yesno {
    print "Are you sure (Y/N)?";
    $answer=<STDIN>
}

To invoke a subroutine—also known as calling a subroutine—you can use either of the following syntax lines:

&yesno();

or

yesno();

You can use the second syntax (without the &) if the subroutine was declared in the code already; the &yesno() syntax is acceptable anywhere. In this book, 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:

sub  countdown {
    for($i=10; $i>=0; $i--) {
        print "$i -";
    }
}
print "T-minus: ";
countdown();
print "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. It is 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 value of the subroutine is computed when the subroutine is called, and then the return value is used in whatever the subroutine was called. Now 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. The return statement is required 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
";
}

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 data that was either hard-coded (2*4) or variables that just happen to have the right data in them ($x for x_greaterthan100()). This limitation creates a problem because functions that rely on data that is hard-coded or expects values 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 behavior of the function, then, can change depending on what was passed to it.

These values given to functions to change their behavior 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 the subroutine, the arguments that were passed 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 a subscript on the array @_ as you would any other array. Just remember that $_[0]—a subscript 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; in this manner, it's more clear what they do. To see what I mean, check out the following example:

sub display_box_score {
    ($hits, $at_bats)=@_;
    print "For $at_bats trips to the plate, ";
    print "he's hitting ", $hits/$at_bats, "
";
}
display_box_score(50, 210);

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

Note

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
";
    print "The second array: @b
";
}
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.")

A mixture of 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."

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.94.153