next up previous contents
Next: Interacting with the Operating Up: Functions Previous: Passing Arrays to Functions   Contents


Using References to Pass Arguments

In order to solve problems such as argument passing in a general way, perl provides the concept of a reference. A reference is a special scalar variable which contains information that perl can use to find and access some other kind of object, usually an array or a hash. By using references, you can pass any arguments you want to a function, since each reference is just a scalar value. In order to use this technique, we must know how to create a reference from some other object, as well as how to convert a reference into the object to which it refers.

To create a reference from an array or hash simply precede the variable's name with a backslash (\). To restore a reference back to the object to which it refers, precede the reference's name with the appropriate symbol, i.e. an at sign (@) for arrays, or a percent sign (\%) for a hash. Because of perl's precedence rules, it is sometimes necessary to surround the reference with curly braces before preceding it with the appropriate symbol. This will be illustrated by the example below.

Suppose we wish to write a function which will take two arrays, verify that they are the same length, and then return an array of that length containing the sum of the corresponding elements from the original arrays. If we could guarantee that the arrays were of the same length, we could just split the argument list in half, but, in general, making assumptions like this is very dangerous. If you are writing a function which needs to manipulate more than one array, it is worthwhile to use references for that purpose.

The implementation of our function could look like this:

     sub add_2_arrays{
        my(@first) = @{$_[0]};
        my(@second) = @{$_[1]};
        my(@answer);
     
        return undef if @first != @second;
         
        foreach $i (0..$#first){ 
            $answer[$i] = $first[$i] + $second[$i];
        }
     
        return(@answer);
      }
The first two statements of the function convert the references passed to the functions back into arrays; note the syntax, especially the curly braces around the variable names. Next, we test to see if the arrays have the same number of elements. Since the not equal (!=) operator works in scalar context, both of the arrays are converted to the number of elements they contain. Finally we add the corresponding elements together, and store them in a localized array called @answer. When calling a function like this, it's very important to pass references to the arrays which are to be added, and not the arrays themselves, because perl will silently fail to perform the desired computations if arrays are passed to the function. So to use the function, the names of the arrays need to be preceded by a backslash before they are passed to add_2_arrays. (To pass unnamed lists, known as anonymous arrays, to a function, the technique is slightly different; see Section [*] for more information.)
     @array1 = (17,23,13,2,7);
     @array2 = (13,18,21,9,5);
     @result = add_2_arrays(\@array1,\@array2);
Since the function returns undef, but will be evaluated in an array context, to check for a length mismatch, you would need to check if the 0th element of the returned array was not defined:
  @array1 = (17,23,13,2,7);
  @array2 = (3,4,5);
  @result = add_2_arrays(\@array1,\@array2);
  print "Length mismatch\n" if(not defined($result[0]));
An alternative would be to have the function make a call to die or warn, but before implementing a solution such as that, make sure that you know how the function will be called. By passing back undef, you can let the calling program decide what it wants to do when a mismatch occurs.


next up previous contents
Next: Interacting with the Operating Up: Functions Previous: Passing Arrays to Functions   Contents
Phil Spector 2002-10-18