Полезная информация

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