home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam

## 10.1. Accessing Subroutine Arguments

### Problem

You have written a function and want to use the arguments supplied by its caller.

### Solution

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) );
}```

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