Recipe 10.1. Accessing Subroutine Arguments
Author: Tom Christiansen & Nathan Torkington
Date: 1999-07-02T01:39:35Z

#

| Chapter 10 Subroutines |

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

### See Also

The section on "Subroutines" in Chapter 2 of Programming Perl and perlsub (1)

10.0. Introduction |  | 10.2. Making Variables Private to a Function