Accessing Subroutine Arguments (Perl Cookbook, 2nd Edition)

## 10.1. Accessing Subroutine Arguments

### 10.1.1. Problem

You have written a function that takes arguments supplied by its caller, and you need to access those arguments.

### 10.1.2. Solution

The special array `@_` holds the values passed in as the function's arguments. Thus, the first argument to the function is in `$_[0]`, the second in `$_[1]`, and so on. The number of arguments is simply `scalar(@_)`.

For example:

>     sub hypotenuse {
>         return sqrt( ($_[0] ** 2) + ($_[1] ** 2) );
>     }

>     $diag = hypotenuse(3,4);  # $diag is 5

Most subroutines 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) );
>     }

### 10.1.3. Discussion

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 or values from a subroutine, use the `return` statement with arguments. 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 you called a function with `(@a`, `@b)`, you'd be giving it all arguments from both arrays. This is the same principle of flattened lists at work as in:

>     @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.

You 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;
>     }

You 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 as arguments to a function that intends to modify those arguments; for example, don't call `trunc_em(1.4`, `3.5`, `6.7)`. If you do, you'll get a runtime exception to the effect of `Modification` `of` `a` `read-only` `value` `attempted` `at` `..`..

The built-in functions `chop` and `chomp` are like that; they modify their caller's variables and return something else entirely. Beginning Perl programmers who notice regular functions that all return some new value—including `int`, `uc`, and `readline`— without modifying those functions' arguments sometimes incorrectly infer that `chop` and `chomp` work similarly. This leads them to write code like:

>     $line = chomp(<>);                  # WRONG

>     $removed_chars = chop($line);       # RIGHT
>     $removed_count = chomp($line);      # RIGHT

until they get the hang of how this pair really works. Given the vast potential for confusion, you might want to think twice before modifying `@_` in your own subroutines, especially if you also intend to provide a distinct return value.

### 10.1.4. See Also

Chapter 6 of Programming Perl and perlsub(1)

Copyright © 2003 O'Reilly & Associates. All rights reserved.