Subroutines are declared using one of these forms:
Prototypes allow you to put constraints on the arguments you provide to your subroutines.sub name {block} sub name (proto) {block}
You can also create anonymous subroutines at run-time, which will be available for use through a reference:
$subref = sub {block};
The ampersand (&
) is the identifier used to
call subroutines.
Most of the
time, however, subroutines can be used in an
expression just like built-in functions.
To call subroutines directly:
To call subroutines indirectly (by name or by reference):name(args); # & is optional with parentheses name args; # Parens optional if predeclared/imported &name; # Passes current @_ to subroutine
&$subref(args); # & is not optional on indirect call &$subref; # Passes current @_ to subroutine
All arguments to a subroutine are passed as a single, flat list of scalars, and return values are returned the same way. Any arrays or hashes passed in these lists will have their values interpolated into the flattened list.
Any arguments passed to a
subroutine come in as the array @_
.
You may use the explicit return
statement to return
a value and leave the subroutine
at any point.
If you want to pass more than one array or hash into or out of a function and have them maintain their integrity, then you will want to pass references as arguments. The simplest way to do this is to take your named variables and put a backslash in front of them in the argument list:
This sends references to the three arrays to the subroutine (and saves you the step of creating your own named references to send to the function). The references to the arrays are passed to the subroutine as the three-member@returnlist = ref_conversion(\@temps1, \@temps2, \@temps3);
@_
array. The subroutine will have to dereference the arguments
so that the data values may be used. Returning references is a simple matter of returning scalars that are references. This way you can return distinct hashes and arrays.
Any variables you use in the function that aren't declared private are global variables. In subroutines, you'll often want to use variables that won't be used anywhere else in your program, and you don't want them taking up memory when the subroutine is not being executed. You also might not want to alter variables in subroutines that might have the same name as global variables.
The my
function declares variables
that are lexically scoped within the subroutine. Lexically scoped
variables are private variables that only exist within the block or
subroutine in which they are declared.
Outside of their scope, they are invisible and can't be altered in any way.
To scope multiple variables at once, use a list in parentheses. You can
also assign a variable in a my
statement:
Dynamic variables are visible to other subroutines called from within their scope. Dynamic variables are defined withmy @list = (44, 55, 66); my $cd = "orb";
local
, and they are not private variables, but rather they are
global variables with temporary values. When a subroutine is executed, the
global value is hidden away, and the local value is used. Once the
scope is exited, the original global value is used. Most of the
time you will want to use my
to localize parameters in a subroutine.Prototypes allow you to design your subroutines to take arguments with constraints on the number of parameters and types of data. To declare a function with prototypes, use the prototype symbols in the declaration line, like this:
In this case, the function expects two scalar arguments. The following table gives the various prototype symbols:sub addem ($$) { ... }
Symbol | Meaning |
---|---|
$ | Scalar |
@ | List |
% | Hash |
& | Anonymous subroutine |
* | Typeglob |
A backslash placed before one of these symbols forces the argument to be that exact variable type. For instance, a function that requires a hash variable would be declared like this:
Unbackslashedsub hashfunc (\%);
@
or %
symbols act exactly alike, and will
eat up all remaining arguments, forcing list context. A $
likewise
forces scalar context on an argument, so taking an array or hash variable for that
parameter would probably yield unwanted results.A semicolon separates mandatory arguments from optional arguments. For example:
requires two arguments: an array variable and a scalar. The third scalar is optional. Placing a semicolon beforesub newsplit (\@$;$);
@
and %
is not necessary since
lists can be null.A typeglob prototype symbol (*
) will always turn its argument
into a reference to a symbol table entry. It is most often used for
filehandles.