Going Deeper

Subroutines are fairly basic concepts that don't involve a large amount of depth in Perl. Nonetheless, there are a few concepts that aren't discussed in this lesson, which are summarized here.

The definitive description of Perl subroutines, because my is an operator, more information about it can also be found in the perlfunc man pages (although we'll also talk more about it on Day 13). See those pages for further details on any of the concepts described in this section.

Local Variables in Blocks

I've made a point of referring to local variables in this section as being defined inside subroutines, and local only as far as those subroutines are running. In reality, local variables can be defined to be local to any enclosing block, not just to subroutines. You can use local variables inside conditionals, loops or labeled blocks, and those local variables will follow the same rules as they do in subroutines as far as hiding global variables of the same name and of being only available to the subroutine in which they are defined. Most of the time, however, local variables make the most sense when they are applied to subroutines and not to other blocks.

Leaving Off the Parentheses for Arguments

When you call built-in functions in Perl, you can call them with their arguments in parentheses, or leave off the parentheses if Perl can figure out where your arguments begin and end. You can actually do the same thing with subroutines, if you want to, but only if these two rules are met:

  • You also call the subroutine without the leading & (with the leading & and Perl will try to use @_ instead)

  • Perl has already seen a declaration or definition of that subroutine previously in the script

Perl, for the most part, is not particular about where in a script a subroutine is defined, as opposed to where it is called (some languages require you to define a subroutine further up in the file from where you call it). Leaving off the parentheses for the arguments is the one exception.

One way to get around this is to predeclare a subroutine at the top of your script, similarly to how you'd declare all your global variables before using them. To do this, just leave off the block part of the subroutine definition:

sub mysubroutine;

With the subroutine declared, you can then call it with arguments with or without parentheses. Don't forget to actually define that subroutine later in your script, however.

Note that common practice among Perl programmers is to include the parentheses, even if it's possible to leave them off. Parentheses make your subroutines easier to read, less error-prone, and more consistent with other programming languages, so consider using this feature sparingly.

Using @_ to Pass Arguments to Subroutines

You've seen how the @_ variable contains the argument list to any subroutine, and is implicitly local to that that subroutine. You can, however, also use @_ inside or outside a subroutine to redefine a set of arguments for the subroutine call.

For example, if you set @_ to a list of elements in the main body of your Perl script, then call a predeclared subroutine with no arguments, Perl will use the values in that array as the arguments to that subroutine. Here's a simple example:

@_ = ("this", "that", "other things");
&mysubroutine;   # no specific args, use @_

In this case, because the subroutine &mysubroutine() was called without ending parentheses, Perl will use the contents of @_ as the arguments to that subroutine. This could be useful for calling ten different subroutines with all the same arguments, for example.

This works for calling nested subroutines as well; you can use the current contents of any @_ variable as the arguments to a nested subroutine. Note that calling a subroutine with any arguments whatsoever, including an empty set of parentheses, overrides the use of @_. Note also that you must have predeclared the subroutine for this to work.

Anonymous Subroutines

Anonymous subroutines are subroutines without names, and they operate sort of like pointers to functions in C. You use anonymous subroutines to create references to a subroutine, and the use Perl's references capabilities to gain access to that subroutine later.

We'll discuss anonymous subroutines more in Day 19, “Working with References.”

Using Subroutine Prototypes

Prototypes are one of those newer features that have snuck into Perl in the minor releases. Added to Perl as of version 5.003, subroutine prototypes enable your subroutines to look and behave just like regular built-in functions—that is, to determine the type of arguments they can accept rather than just stuffing them all into a list.

Subroutine prototypes only effect subroutines called without a leading &; you can call that same subroutine with a &, but the prototype will be ignored. In this way you can call a subroutine like a function or call it like a subroutine depending on your mood or for any other reason.

To declare or define a subroutine with a prototype, use one of the following:

sub subname (prototype);   # predeclaration
sub subname (prototype) {
   ...
}

The subname is, of course, the name of the subroutine. The prototype contains special characters referring to the number and type of arguments:

  • $ refers to a scalar variable, @ to an array, % to a hash. @ and % indicate list context and must appear last in the argument list (because they eat up the remaining arguments).

  • Semicolons separate required arguments from optional arguments.

  • Backslashed characters require arguments that start with that actual character.

So, for example, a subroutine with a prototype of ($$) would expect two scalar variables as arguments. One with ($$;@) would require two scalars, and have an optional list. One with (@) requires a single list variable argument starting with @.

While subroutine prototypes might seem nifty, the fact that they are only available in newer versions of Perl might be problematic because you must be assured that the system you run your scripts on will have at least Per 5.003 installed. If you are only running your scripts on your own system this isn't a problem. If they're intended for wider use, it might be, although there is a way to figure this out at runtime which was described on Day 8, “Manipulating Lists and Strings.”)

For more information on subroutine prototypes, see the perlsub man page.

The caller Function

One function I didn't mention in the body of this lesson is caller. The caller function is used to print out information about where a subroutine was called from (which can be sometimes useful for debugging). For more information, see the perlfunc man page.

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

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