Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl foreach loop in subroutine

I know the subroutine in perl pass arg by reference. But in the below code, the foreach loop in the subroutine should not be changing the value for @list because the my $i should be creating a new lexically scope var $i. Any assignment to $i should be lexically scope but not changing the @list value.

Can anyone explain what is happening inside the foreach loop that causes the value change to @list?

sub absList {    
    foreach my $i (@_) {
        $i = abs($i);
    }
}

@list = (-2,2,4,-4);
absList(@list);
print "@list";

Outputs:

2 2 4 4
like image 553
user2763829 Avatar asked Jun 07 '14 12:06

user2763829


2 Answers

$i is aliased to elements of @_ array due foreach feature (and @_ elements are aliased to elements of the @list due @_ magic).

From perldoc

If any element of LIST is an lvalue, you can modify it by modifying VAR inside the loop. Conversely, if any element of LIST is NOT an lvalue, any attempt to modify that element will fail. In other words, the foreach loop index variable is an implicit alias for each item in the list that you're looping over.

If you want to avoid such behavior, don't iterate directly over @_ array, ie.

sub absList {
    my @arr = @_;
    foreach my $i (@arr) {
        $i = abs($i);
    }
}
like image 156
mpapec Avatar answered Sep 21 '22 23:09

mpapec


$i here refers the list elements which it gets from @_, that's why changing $i causes change in respective list element.

like image 21
Chankey Pathak Avatar answered Sep 22 '22 23:09

Chankey Pathak