Returning Values from Subroutines - Page 19
July 27, 2001
Subroutines can return values in one of two ways, either
implicitly, by reaching the end of their block, or explicitly,
through the use of the return statement.
If no explicit return statement is given, then the
return value of a subroutine is the value of the last statement
executed (the same as for ordinary bare blocks). For example, the
string 'implicit return value' is returned by the
following simple subroutine because it is the last (and in this
case, only) statement in the subroutine:
sub implicit_return {
my $string = "implicit return value";
}
Or even just:
sub implicit_return {
"implicit return value";
}
To explicitly define the return value we use the
return statement; return takes an
expression as its argument, and returns its value to the caller:
sub explicit_return {
return "explicit return value";
}
It follows from this that it is never actually necessary to use
return when passing back a value from the last
statement in the subroutine. However, it is good practice, to
indicate that we know what we are doing and are aware of what the
return value is. If a subroutine does not have an explicit
return, the implication is that it does not return a
value of use.
There is nothing to stop us putting several return
statements into the same subroutine. Whichever
return statement is encountered first will cause the
subroutine to exit with the value of the supplied expression,
aborting the rest of the subroutine. The following simple
subroutine illustrates this:
sub list_files {
$path = shift;
return "" unless defined $path;
# return an empty string if no path
return join(', ', glob "$path/ * ");
# return comma separated string
}
Here we have used two return statements. The first
returns the undefined value if we fail to supply a pathname for
the subroutine to look at. The second is only reached if a
defined (but not necessarily valid or existent) path is supplied.
We could call this subroutine with code that looks like this:
if (my $files = list_files ("/path/to/files")) {
print "Found $files \n";
}
Multiple return statements are a convenient way to
return values from a subroutine as soon as the correct value has
been computed, but for large subroutines they should be used with
caution. Many programming problems stem from over-complex
subroutines that have more than one return in them,
causing a crucial piece of code to be skipped in some cases and
not others. This is often a sign that the subroutine is too large
to be easily maintained and should be split into smaller
functional blocks. Otherwise, it is better to funnel the
execution of the subroutine to just one return
statement at the end, or otherwise make it very clear in the
source where all the exits are.
The list_files subroutine above works, but it is a
little clumsy. It does not allow us to distinguish between an
undefined path and a path on which no files were found. It also
returns the files found as a string rather than a list, which
would have been more useful. The first of these we can fix by
using the undefined value to indicate an error. The second we can
fix by returning a list, or more cunningly, by detecting the
calling context and returning a scalar or list value as
appropriate. We will cover each of these in turn.
Optional Parameters - Page 18
Professional Perl Programming
Returning the Undefined Value - Page 20
|