abhishes has asked for the wisdom of the Perl Monks concerning the following question:

Hello Perl Monks,

I wrote the following program and the output really confused me.

use warnings; use strict; my @a = ("a", "b", "c"); Foo(\@a); print "$_ " foreach(@a); sub Foo { my $refA = shift; my @b = @$refA; $b[0] = "hello"; $b[1] = "world"; $b[2] = "Perl"; }

The output of the code was "a b c ".

How?? Didn't I pass a reference? If so, when I alter items against the reference, the change should be visible outside the subroutine as well!

I searched perl monks site found this node

but its still not clear to me... why were my changes lost.

regards,
Abhishek.

Replies are listed 'Best First'.
Re: Changing items of an array in a function
by Anonymous Monk on May 14, 2003 at 13:46 UTC

    Because you copied the referenced array's contents to a local copy and then modfied the local copy. You never copied it back. Try

    use warnings; use strict; my @a = ("a", "b", "c"); Foo(\@a); print "$_ " foreach(@a); sub Foo { my $refA = shift; # my @b = @$refA; $refA->[0] = "hello"; $refA->[1] = "world"; $refA->[2] = "Perl"; }
Re: Changing items of an array in a function
by broquaint (Abbot) on May 14, 2003 at 13:51 UTC
    How?? Didn't I pass a reference?
    That you did, but you also copied the contents of the array that reference pointed to into a new array, which as you can guess, isn't going to effect the array that said reference is pointing to. Here's what you really want
    use warnings; use strict; my @a = ("a", "b", "c"); Foo(\@a); print "$_ " foreach(@a); sub Foo { my $refA = shift; ## dereference the array $refA->[0] = "hello"; $refA->[1] = "world"; $refA->[2] = "Perl"; } __output__ hello world Perl
    It might be a good idea to learn more about references and how they work in perl. See. perlreftut, perlref, perldsc and tye's References quick reference for further information.
    HTH

    _________
    broquaint

Re: Changing items of an array in a function
by edan (Curate) on May 14, 2003 at 13:52 UTC

    You did pass a reference, but then you created a new array:

    my @b = @$refA;

    And then you modify that new array which is only scoped inside the function, which leaves the array-by-reference argument as-is.

    If you change your function to look like this, it might do what you were expecting:

    sub Foo { my $refA = shift; $refA->[0] = "hello"; $refA->[1] = "world"; $refA->[2] = "Perl"; }
    --
    3dan
Re: Changing items of an array in a function
by physi (Friar) on May 14, 2003 at 15:45 UTC
    You can also return your @b array to the main like that:
    use warnings; use strict; my @a = ("a", "b", "c"); @a = Foo(\@a); print "$_ " foreach(@a); sub Foo { my $refA = shift; my @b = @$refA; $b[0] = "hello"; $b[1] = "world"; $b[2] = "Perl"; return @b; }
    -----------------------------------
    --the good, the bad and the physi--
    -----------------------------------