Daanish
Daanish

Reputation: 1091

An array and a variable as parameters in subroutine in Perl

Consider:

sub abc()
{

}

abc(@array, $a);

How do I access @array and $a in subroutine abc()?

I know about $_[0] and $_[1], but I wasn't sure if I can use it for arrays.

Upvotes: 2

Views: 1597

Answers (4)

jchips12
jchips12

Reputation: 1227

You have two options:

  1. Pass the scalar variable first (the dirty way)

    abc($a, @array);
    

    Then receive the parameters in subroutine as

    my ($a, @array) = @_;
    
  2. Pass your array as reference by adding a backslash before the array variable (recommended)

    abc(\@array, $a);
    

    Then receive the parameters in subroutine as

    my ($array_ref, $a) = @_;
    

    And dereference the $array_ref

    my @array = @$array_ref;
    

More information about perlref.

Upvotes: 6

Oleg V. Volkov
Oleg V. Volkov

Reputation: 22421

You access a sub's arguments with the @_ array. The first argument is $_[0], the second - $_[1], etc. In this particular case, your array will be unrolled to list of its elements, so $_[0] is $array[0], $_[1] is $array[1] and then after all those elements, last element of @_ will be the value of $a.

If you want to avoid unrolling that always happens when you use an array in a list context, use a reference to the array instead. References to arrays and hashes are created using \. So call your function like:

abc(\@array, $a);

After that, $_[0] will have reference to @array and $_[1] will be $a. To access array elements through reference, use -> operator. $_[0]->[2] is same as $array[2]. Actually you can even drop -> as long as it is between brackets, so $_[0][2] will work too. See more details on references in perlref.

Upvotes: 6

dan1111
dan1111

Reputation: 6566

The other answers explained the two basic approaches. However, it is important to note that there is a big difference between the two: When you pass an array by reference, any changes you make to it also change the original array. Here is an example:

use warnings;
use strict;

my @array = (1, 2, 3, 4, 5);

sub by_ref
{
    my $array_ref = $_[0];
    @$array_ref = (0, 0, 0);
    print "Array inside by_ref: @$array_ref\n";
}

sub by_val
{
    my @array_copy = @_;
    @array_copy = (0,0,0);
    print "Array inside by_val: @array_copy\n";
}

by_val(@array);

print "Original array after calling by_val: @array\n";

by_ref(\@array);

print "Original array after calling by_ref: @array\n";

If you do pass by reference, you need to keep this behavior in mind, making a copy of the referenced array if you don't want changes made in your sub to affect the original.

Upvotes: 2

Nikhil Jain
Nikhil Jain

Reputation: 8332

It would be nice if you pass the array reference instead of an array as mentioned by Oleg V. Volkov like

sub abc()
{
    my ( $array, $a ) = @_; #receiving the paramters
    my @arr = @{$array}; # dereferencing the array
}

abc(\@array,$a);

Upvotes: 0

Related Questions