37

Possible Duplicate: How do pass one array and one string as arguments to a function?

I have a function, or subroutine, that takes in the first parameter as an array and the second parameter as a scalar. For example,

sub calc {
    my @array = $_[0];
    my $scalar = $_[1];
    print @array, $scalar;
}

The problem is that the function is making the array equal to the first value of the array passed in, and the scalar to be the second value of the array passed in. When I want the first array to be the entire array, I do not need to make a deep copy of the array. For example,

my @array = ('51', 'M');
my $scalar = 21;

and

calc(@array, $scalar)

will print 51 M when I want 51 M 21.

Community
  • 1
  • 1
E.Cross
  • 2,087
  • 5
  • 31
  • 39

5 Answers5

69

You need to pass it in as a reference:

calc(\@array, $scalar)

And then access it as: my @array = @{$_[0]};

happydave
  • 7,127
  • 1
  • 26
  • 25
19

Either use a reference to the array as the first argument, or reverse the arguments so that the scalar is first and the array comes afterwards:

sub reversed_args
{
   my($scalar, @array) = @_;
   # ...
   print @array, $scalar, "\n";
}

my @array = ('51', 'M');
my $scalar = 21;

reversed_args($scalar, @array);

Do not try Perl prototypes (two articles, one on Stack Overflow, one on PerlMonks).

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • What is the gist of not attempting to use prototypes? – Peter Mortensen Apr 24 '16 at 10:00
  • 2
    The shortest form is "Do not use Perl prototypes"; the next shortest form is "Perl function prototypes don't work as you expect and the experts recommend that you don't attempt to use them". The long-winded version runs something along the lines of "Perl prototypes are a failed experiment that cause more grief and consternation than they do useful assistance when used, leading to hard to diagnose problems — down this path lies despair and madness". – Jonathan Leffler Apr 24 '16 at 14:04
13

Pass your array to the calc subroutine as an array ref:

calc(\@array, $scalar);

Then in your calc subroutine, you initialize your input parameters like this:

sub calc {
  my($array_ref, $scalar) = @_;

  foreach my $item (@$array_ref) {
    # process each item in the array ref
  }
}
Sam Choukri
  • 1,874
  • 11
  • 17
11

You can pass a reference to the array to your function:

calc(\@array, $scalar);

When you need to access elements of @array in your subroutine you can do it like this:

my $array = $_[0];

# access first element of array
print $array->[0];

Edit: Since this is a reference to the original array any changes made in the subroutine will be reflected in the original array.

Peter Willsey
  • 1,078
  • 6
  • 18
  • 2
    Cool, I knew it was some syntax problem, thank you! – E.Cross May 23 '12 at 23:11
  • @Dan, It wasn't a syntax error. The problem is that you didn't understand that a sub call's argument list is evaluated as one expression, not a series of comma-separated expressions. – ikegami May 23 '12 at 23:18
  • 1
    Well I figured that much out, so I would say that I disagree. I simply didn't know how to tell perl that I am passing through an array. – E.Cross May 23 '12 at 23:23
  • @Dan If you're satisfied with my answer would you mind accepting it ? – Peter Willsey May 23 '12 at 23:56
  • 1
    You should mention to the OP that passing a reference will allow the sub to alter the original array. – TLP May 24 '12 at 11:59
1

The argument list in a Perl subroutine is simply a flat array. If you want to pass a distinct array, you must pass it as an array reference.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Barton Chittenden
  • 4,238
  • 2
  • 27
  • 46