Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

references--hard vs anonymous operational weirdness

by hill (Sexton)
on Mar 23, 2008 at 03:12 UTC ( #675719=perlquestion: print w/replies, xml ) Need Help??

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

When this:
$data{$tab} = \@array;
is executed in a loop where $tab and @array change, every resulting $data{$tab} contains the value of the @array associated with the final $tab.

Changing the initial line to invoke an anonymous reference:
$data{$tab} = [@array]
works a treat.

Any explanations would be most welcome.

  • Comment on references--hard vs anonymous operational weirdness

Replies are listed 'Best First'.
Re: references--hard vs anonymous operational weirdness
by hipowls (Curate) on Mar 23, 2008 at 03:19 UTC

    When you have \@array you create a reference to an array. Every time through the loop it is a reference to the same array. On the other hand [@array] is an anonymous array constructor that does a shallow copy of @array and creates a reference to the new copy.

      Only if @array was declared outside the loop.</nit>

      my @array; for my $tab ( @things ) { @array = frobnicate( $tab ); ## As you've seen, this leaves everything pointing at the same array $data{ $tab } = \@array; }

      Were @array declared inside the loop you'd get a fresh instance each time through.

      for my $tab ( @things ) { my @array = frobnicate( $tab ); $data{ $tab } = \@array; }

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

        Quite right, I'd got caught by an optimization. I ran (adjusting code to your example)

        for my $tab ( 1 .. 3 ) { my @array = frobnicate($tab); printf "Array ref: %s\n", \@array; printf "Annoymous: %s\n", [@array]; } sub frobnicate { return ( 0 .. shift ); } __END__ Array ref: ARRAY(0x826a924) Annoymous: ARRAY(0x8183a54) Array ref: ARRAY(0x826a924) Annoymous: ARRAY(0x826d818) Array ref: ARRAY(0x826a924) Annoymous: ARRAY(0x82115f8)
        The same address even though @array is declared in the loop. The variable is being reused. Assigning \@array to something prevents the optimization.
        my %data; for my $tab ( 1 .. 3 ) { my @array = frobnicate($tab); printf "Array ref: %s\n", \@array; printf "Annoymous: %s\n", [@array]; $data{$tab} = \@array; } sub frobnicate { return ( 0 .. shift ); } __END__ Array ref: ARRAY(0x826a924) Annoymous: ARRAY(0x8183a54) Array ref: ARRAY(0x819f318) Annoymous: ARRAY(0x8183798) Array ref: ARRAY(0x826ade8) Annoymous: ARRAY(0x819f304)
        Something to bear in mind when benchmarking.

Re: references--hard vs anonymous operational weirdness
by bobf (Monsignor) on Mar 23, 2008 at 03:40 UTC

    As mentioned by both hipowls and Fletch, the issue is likely that your @array is declared outside of the loop. If you wanted to prove to yourself that a new array ref is being created, or that an existing one is being reused, you can examine the memory address by printing the reference (see perldsc). The following example illustrates the difference between an array declared outside the loop and one that is declared on every iteration.

    use strict; use warnings; my %hash; my $same_array = []; for( 1 .. 3 ) { $hash{$_}{same} = $same_array; $hash{$_}{new} = []; print "$_: $hash{$_}{same} vs $hash{$_}{new}\n"; }
    Output:
    1: ARRAY(0x34f88) vs ARRAY(0x35d50) 2: ARRAY(0x34f88) vs ARRAY(0x1854e88) 3: ARRAY(0x34f88) vs ARRAY(0x1854e34)

Re: references--hard vs anonymous operational weirdness
by hill (Sexton) on Mar 23, 2008 at 06:58 UTC
    Gentle folks,

    Thanks for your prompt and interesting attention. However, the array in question is defined inside the loop. A bit more of the code would certainly help the explanation.

    opendir THISDIR, "."; while ($file = readdir THISDIR) { if ($file =~ /csv$/i) { open(INPUT, "$file") or die "Could not open $file. \n"; @array = <INPUT>; ($tab) = ($file =~ /.*\.(T\w+)\./); # Separate tab number from +file name $data{$tab} = [@array]; close INPUT; } }

    This one seems to work. With the \@array structure each array is correct when established but is over written the next time through the loop. Ideas??

    Many thanks.

        The perl-o-sphere has increased by some quantum amount.

        Somehow during the past couple of years fooling with perl, I missed that aspect of variable scoping. This points me back into that subject for further exploration.

        Many thanks for the answer and insight to this query.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://675719]
Approved by kyle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (4)
As of 2020-10-23 03:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My favourite web site is:












    Results (234 votes). Check out past polls.

    Notices?