You have written a function and want to use the arguments supplied by its caller.
All values passed as arguments to a function are in the special array
@_
. Thus, the first argument to the function is in
$_[0]
, the second is in
$_[1]
, and so on. The number of arguments is therefore
scalar(@_)
.
For example:
sub hypotenuse { return sqrt( ($_[0] ** 2) + ($_[1] ** 2) ); } $diag = hypotenuse(3,4); # $diag is 5
Your subroutines will almost always start by copying arguments into named private variables for safer and more convenient access:
sub hypotenuse { my ($side1, $side2) = @_; return sqrt( ($side1 ** 2) + ($side2 ** 2) ); }
It's been said that programming has only three nice numbers: zero, one, and however many you please. Perl's subroutine mechanism was designed to facilitate writing functions with as many - or as few - elements in the parameter and return lists as you wish. All incoming parameters appear as separate scalar values in the special array
@_
, which is automatically local to each function (see
Recipe 10.13
). To return a value from a subroutine, use the
return
statement with an argument. If there is no
return
statement, the return value is the result of the last evaluated expression.
Here are some sample calls to the
hypotenuse
function defined in the Solution:
print hypotenuse(3, 4), "\n"; # prints 5 @a = (3, 4); print hypotenuse(@a), "\n"; # prints 5
If you look at the arguments used in the second call to
hypotenuse
, it might appear that only one argument was passed: the array
@a
. This isn't what happens - the elements of
@a
are copied into the
@_
array separately. Similarly, if we called a function with
(@a,
@b)
, we'd be giving it all the arguments in both arrays. This is the same principle of flattened lists at work as when we say:
@both = (@men, @women);
The scalars in
@_
are implicit aliases for the ones passed in, not copies. That means changing the elements of
@_
in a subroutine changes the values in the subroutine's caller. This is a holdover from before Perl had proper references.
So, we can write functions that leave their arguments intact, by copying the arguments to private variables like this:
@nums = (1.4, 3.5, 6.7); @ints = int_all(@nums); # @nums unchanged sub int_all { my @retlist = @_; # make safe copy for return for my $n (@retlist) { $n = int($n) } return @retlist; }
We can also write functions that change their caller's variables:
@nums = (1.4, 3.5, 6.7); trunc_em(@nums); # @nums now (1,3,6) sub trunc_em { for (@_) { $_ = int($_) } # truncate each argument }
Don't pass constants to this kind of function, as in
trunc_em(1.4,
3.5,
6.7)
. If you try, you'll get a run-time exception saying
Modification
of
a
read-only
value
attempted
at
...
.
The built-in functions
chop
and
chomp
work like this, modifying their caller's variables and returning the character(s) removed. People are used to such functions returning the changed values, so they often write things like:
$line = chomp(<>); # WRONG
until they get the hang of how it works. Given this vast potential for confusion, you might want to think twice before modifying
@
_ in your
subroutines.
The section on "Subroutines" in Chapter 2 of Programming Perl and perlsub (1)