in reply to Possible bug with array pointer

Hi jockel,

That's the intended behavior. See Foreach Loops (emphasis mine):

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.

Hope this helps,
-- Hauke D

Replies are listed 'Best First'.
Re^2: Possible bug with array pointer
by jockel (Beadle) on Jan 10, 2017 at 18:59 UTC

    Thank you!

    I've been programming perl for almost 20 years and didn't know that!

    I guess I've never actually modified the assigned foreach-variable or never used the array afterwards! What are the odds ;-)

    The lesson learned: You never stop learning!

    -----BEGIN PERL GEEK CODE BLOCK----- Version: 0.01 P++>*$c--->---P6 > R >++++$M+>+++$O+++>+++$MA->+++$E > PU->++BD->-C+>+$D+>+$S->+++X >+WP >+++MO!PP n?CO--PO!>!(!)o?G!A--OLC--OLCC--OLJ--Ee !Ev-Eon-uL++>*uB!uS!uH-uo!w->!m+ ------END PERL GEEK CODE BLOCK------

      Hello jockel,

      A standard idiom (see Re: Containing 'use lib' statements in modules to their own namespace) for removing (“breaking”) the alias is to assign the aliased variable to a lexical variable inside the loop:

      use strict; use warnings; my $arrayref = ['A','_B','C']; for my $str (@$arrayref) { print "BEFORE: str = $str\n"; } for (@$arrayref) { my $str = $_; $str =~ s/^_//; print "INNER: str = $str\n"; } for my $str (@$arrayref) { print "AFTER: str = $str\n"; }

      Output:

      13:30 >perl 1738_SoPW.pl BEFORE: str = A BEFORE: str = _B BEFORE: str = C INNER: str = A INNER: str = B INNER: str = C AFTER: str = A AFTER: str = _B AFTER: str = C 13:30 >

      BTW, an underscore character has no special meaning in a regex, so it doesn’t need to be escaped. Also, in the absence of an /m modifier, ^ can only ever match once, at the beginning of the string, so the /g modifier is redundant.

      Hope that helps,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Thank you for your tips =)

        I solved it by copying the referenced array to a "normal array" before the foreach. TMTOWTDI =)

        I usually escape more than needed. Better safe than sorry. About the redundancy with ^ and /g, I totally agree!

      BTW, you do not need the braces to access a simple scalar reference as an array:
      foreach my $str (@$arrayref) { print "BEFORE: str = $str\n"; }
      will work just as well.
      The extra braces are needed when there is a subscript. @{$arrayref->[2]}

        Thanks. That I actually knew, but in my opinion it's more clear to read when using braces.

        And in the real world case where I was hit by this unknown "oddity" the code looked like this, before the change.

        foreach my $var (@{$self->get('SAMPLEIDS')}) { $var =~ s/_//g; push(@temp_SAMPLEIDS, $var); }