Why is Perl foreach variable assignment modifying the values in the array?

前端 未结 7 2309
一整个雨季
一整个雨季 2020-12-18 19:58

OK, I have the following code:

use strict;
my @ar = (1, 2, 3);
foreach my $a (@ar)
{
  $a = $a + 1;
}

print join \", \", @ar;

and the outp

7条回答
  •  盖世英雄少女心
    2020-12-18 20:05

    As others have said, this is documented.

    My understanding is that the aliasing behavior of @_, for, map and grep provides a speed and memory optimization as well as providing interesting possibilities for the creative. What happens is essentially, a pass-by-reference invocation of the construct's block. This saves time and memory by avoiding unnecessary data copying.

    use strict;
    use warnings;
    
    use List::MoreUtils qw(apply);
    
    my @array = qw( cat dog horse kanagaroo );
    
    foo(@array);
    
    
    print join "\n", '', 'foo()', @array;
    
    my @mapped = map { s/oo/ee/g } @array;
    
    print join "\n", '', 'map-array', @array;
    print join "\n", '', 'map-mapped', @mapped;
    
    my @applied = apply { s/fee//g } @array;
    
    print join "\n", '', 'apply-array', @array;
    print join "\n", '', 'apply-applied', @applied;
    
    
    sub foo {
       $_ .= 'foo' for @_;
    }
    

    Note the use of List::MoreUtils apply function. It works like map but makes a copy of the topic variable, rather than using a reference. If you hate writing code like:

     my @foo = map { my $f = $_; $f =~ s/foo/bar/ } @bar;
    

    you'll love apply, which makes it into:

     my @foo = apply { s/foo/bar/ } @bar;
    

    Something to watch out for: if you pass read only values into one of these constructs that modifies its input values, you will get a "Modification of a read-only value attempted" error.

    perl -e '$_++ for "o"'
    

提交回复
热议问题