2

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.

1

4 Answers 4

6

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you @Oleg V. Volkov. Can you elaborate on the referencing of an array? I'll give it to you if you do that.
I'll give it to you. I see what you did there.
6

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.

3 Comments

The first way isn't dirty in my humble opinion. It has different semantics.
I agree it has different semantics. I say dirty because it will lead to something else if you have a third variable to pass other than scalar.
The first method is used by various built-in functions (join and sprintf, for example). There is nothing wrong with it as long as it fits what you are doing.
2

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.

4 Comments

You can change without reference just as easily. Try: sub change { $_[1] = 42 }; my @arr = (1, 2, 3); change(@arr); print $arr[1], "\n";
@OlegV.Volkov, yes, that is a good point. However, I think the distinction between the two is still important. Normal convention is to copy passed parameters from @_ into lexical variables, but with pass-by-reference that doesn't stop you from modifying the original.
If I need the changes to reflect in my original array what will I have to do. If the answer is too big please post it as another answer...Thank you dan1111.
@Daanish, using pass-by-reference, as illustrated above in the sub by_ref, will change the original array. Alternatively, you could alter @_ directly as Oleg V. Volkov showed in his comment.
0

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);

2 Comments

@Zaid, actually the prototype is a serious error. This code won't run, because now abc does not accept any arguments.
dan1111 is right...I just faced this problem while running this code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.