scope of MY in FOREACH with global array

Discussion in 'Perl Misc' started by Bill, Jul 17, 2004.

  1. Bill

    Bill Guest

    I've been programming perl for a while now and I can't believe something so
    simple is confusing me. Take a look at the following code:

    -------------------------
    #!/usr/bin/perl -w

    # global array definition
    my @array = ("a","b","c");

    sub print_array {
    foreach my $element (@array) {
    $element .= "9";
    print $element . "\n";
    }
    }

    for ($i = 0; $i < 3; $i++) {
    &print_array();
    }
    ------------------------

    The output is as follows:

    a9
    b9
    c9
    a99
    b99
    c99
    a999
    b999
    c999

    What I expected was:

    a9
    b9
    c9
    a9
    b9
    c9
    a9
    b9
    c9

    I thought that "my" would make a copy of each array element whose scope was
    limited to the subroutine in which it was defined. But it seems that
    modifying the elements locally is modifying them in the global array as
    well. What am I missing here?

    -Bill
     
    Bill, Jul 17, 2004
    #1
    1. Advertising

  2. Bill wrote:
    > -------------------------
    > #!/usr/bin/perl -w
    >
    > # global array definition
    > my @array = ("a","b","c");
    >
    > sub print_array {
    > foreach my $element (@array) {
    > $element .= "9";
    > print $element . "\n";
    > }
    > }
    >
    > for ($i = 0; $i < 3; $i++) {
    > &print_array();
    > }
    > ------------------------

    [...]
    > I thought that "my" would make a copy of each array element whose
    > scope was limited to the subroutine in which it was defined. But it
    > seems that modifying the elements locally is modifying them in the
    > global array as well. What am I missing here?


    Simple. The loop variable ($element in this case, $_ by default) is an
    _alias_ of the array element, not a copy. That means, when you write
    $element .= "9" this has the same effect as using $array[$CURRENTINDEX] .=
    "9". Otherwise it would be impossible to use such a loop to alter the array
    elements. And because @array is global those changes stick.

    Now, the scoping rule for my effect $element. That means, if there were a
    global variable $element, then that global variable would have been
    protected from undesired changes by the "my $element".

    In short: the "my" localizes the variable $element, but not the variable
    @array.

    jue
     
    Jürgen Exner, Jul 17, 2004
    #2
    1. Advertising

  3. "Bill" <> writes:

    > foreach my $element (@array) {


    > I thought that "my" would make a copy of each array element


    No, the for-loop interator variable is an _alias_ not a _copy_ of an
    element in the list over which you are iterating. Changes made to the
    loop iterator variable $elmenet are, therefore, changes to acual
    elements of @array.

    --
    \\ ( )
    . _\\__[oo
    .__/ \\ /\@
    . l___\\
    # ll l\\
    ###LL LL\\
     
    Brian McCauley, Jul 17, 2004
    #3
  4. Bill

    Paul Lalli Guest

    On Sat, 17 Jul 2004, Bill wrote:

    > I've been programming perl for a while now and I can't believe something so
    > simple is confusing me. Take a look at the following code:
    >
    > -------------------------
    > #!/usr/bin/perl -w
    >
    > # global array definition
    > my @array = ("a","b","c");
    >
    > sub print_array {
    > foreach my $element (@array) {
    > $element .= "9";
    > print $element . "\n";
    > }
    > }
    >
    > for ($i = 0; $i < 3; $i++) {
    > &print_array();
    > }
    > ------------------------
    >
    > I thought that "my" would make a copy of each array element whose scope was
    > limited to the subroutine in which it was defined. But it seems that
    > modifying the elements locally is modifying them in the global array as
    > well. What am I missing here?


    You're missing the difference between a value in memory and the name that
    refers to it. The 'symbol' (for lack of a better term here) called
    $element is is scoped to only within the foreach loop. However, that
    symbol represents an alias to the values in @array. Because it's an
    alias, not a copy, you are directly modifying @array. If you were to try
    to access $element outside the foreach loop, it would have no value.

    In short, the 'name' $element is what's scoped, not the memory location it
    represents.

    Paul Lalli
     
    Paul Lalli, Jul 17, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Tim Shoppa
    Replies:
    45
    Views:
    530
    Darren Dunham
    Dec 23, 2003
  2. Gavin Sherlock
    Replies:
    1
    Views:
    103
    Uri Guttman
    Dec 10, 2003
  3. David K. Wall

    References to an array in a foreach

    David K. Wall, Oct 14, 2004, in forum: Perl Misc
    Replies:
    14
    Views:
    188
    Eric Bohlman
    Oct 19, 2004
  4. Tomasz Chmielewski

    foreach - sorted array the way I want?

    Tomasz Chmielewski, Dec 10, 2009, in forum: Perl Misc
    Replies:
    3
    Views:
    170
    Jürgen Exner
    Dec 11, 2009
  5. divyajacob
    Replies:
    8
    Views:
    140
    Uri Guttman
    Jun 15, 2010
Loading...

Share This Page