2

I have troubles using a function in Perl.

My function has 2 arguments which are arrays :

sub get_coordinate {
    my (@array_col, @array_lin) = (@_);

    do some stuff
}

I call it this way :

    $index_col                  = int(rand(10));
    $index_lin                  = int(rand(10));
    @array_col                  = (0,0,0,0,0,0,0,0,0,0);
    @array_lin                  = (0,0,0,0,0,0,0,0,0,0);
    $array_col[$index_col]      = 1;
    $array_lin[$index_lin]      = 1;

    get_coordinate(@array_col, @array_lin);

My problem is that I get the error message : Use of uninitialized value within @array_lin in numeric eq (==) at switch.pl line 82 (#1) (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables.

I don't understand why @array_col is initialized an not @array_lin.

When I print @array_col and @array_lin inside the function this way :

print "@array_col\n@array_lin\n";

I get : 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0

Any idea ?

Thx, SLP

6
  • 4
    It is not possible to pass two array arguments by value, all parameter will end up in the first array. Pass them by reference instead. For example, get_coordinate(\@array_col, \@array_lin) Commented Feb 27, 2019 at 10:39
  • Thanks for your answer. Commented Feb 27, 2019 at 10:40
  • What do you mean by "Pass them by reference" ? Commented Feb 27, 2019 at 10:40
  • It's not an answer! He's probably writing one now though. Commented Feb 27, 2019 at 10:40
  • @SLP Re: "What do you mean by pass by reference": See perlref Commented Feb 27, 2019 at 10:41

2 Answers 2

8

In Perl, all lists are flat. These two lists are equivalent.

( 1, 2, ( 3, 4, ( 5 ), (6, 7), 8), (), )
( 1, 2, 3, 4, 5, 6, 7, 8 )

The same thing also happens when take several arrays and stick them in a list.

my @foo = (1, 2, 3);
my @bar = (4, 5, 6);
my @new = (@foo, @bar); # 1, 2, 3, 4, 5, 6

When you pass things to a function, those things get turned into a list of arguments. Therefore, the arrays will both end up in one list, like @foo and @bar above.

frobnicate(@foo, @bar);

When you assign something in list context, the entire list will be assigned left to right. For scalars in the list on the left-hand-side this means they will get their values. But as soon as there is an array, this will be greedy. It will suck up all the remaining values.

my ($one, $two, @rest, $will_be_undef) = (1, 2, 3, 4, 5, 6);

The values will be assigned like this:

$one = 1;
$two = 2;
@rest = ( 3, 4, 5, 6 );
$will_be_undef = undef;

What you need to do to pass two arrays is to take references, and dereference them in our function.

frobnicate( \@foo, \@bar );

sub frobnicate {
    my ($first_array, $second_array) = @_;

    my @foo = @{ $first_array };
    my @bar = @{ $second_array };

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

1 Comment

Thank you for the well detailed answer
2

Assigning to several arrays (or hashes) doesn't do what you think:

my (@array1, @array2) = ...

The first array gets all the elements. How should it know where to stop?

You can use array references instead:

sub get_coordinate {
    my ($arr1, $arr2) = @_;
    my @arr1 = @$arr1;
    my @arr2 = @$arr2;
    ...
}
get_coordinate(\@array1, \@array2);

Comments

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.