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

The following snippet when the loop ends, every key is associated with the data for the last line.There is only one array (@file_lines). All the hash values are references (\@file_lines) to that array.How to create an anonymous array for each line and store a reference to that array in the hash?

foreach my $plf (@plf_files) { chomp($plf); open my $match, '<',"$start_dir\\$plf" or die "could not open '$plf' $ +!"; my @file_lines = <$match>; $Hash_filenames{$plf}=\@file_lines; }
  • Comment on How to create an anonymous array for lines in a file and store a reference to that array in the hash
  • Download Code

Replies are listed 'Best First'.
Re: How to create an anonymous array for lines in a file and store a reference to that array in the hash
by kcott (Archbishop) on Oct 29, 2010 at 09:39 UTC

    In this example, note how the references remain the same and the array contents are overwritten:

    $ perl -wE 'for (0 .. 1) { my @x = $_ == 0 ? qw{a b} : qw{c d e}; say +\@x; say @x; }' ARRAY(0x100a1d40) ab ARRAY(0x100a1d40) cde

    When you enter the loop, the array comes into existence and the reference count is set to 1. When you exit the loop, it goes out of scope and no longer exists; the reference count drops back to zero. With the reference count at zero, the reference can be reused on each subsequent iteration.

    This seems to emulate what you are referring to in your description.

    If you store the array reference in a variable that was created outside of the loop, the reference count is incremented again (i.e. to 2). When you exit the loop, the reference count drops down to 1. As the reference count is not zero, a new reference is created on each iteration. Here's another example showing that:

    $ perl -wE 'my %h; for (0 .. 1) { my @x = $_ == 0 ? qw{a b} : qw{c d e +}; $h{$_} = \@x; say \@x; say $h{$_}; say @x; }' ARRAY(0x100a1d10) ARRAY(0x100a1d10) ab ARRAY(0x10053c88) ARRAY(0x10053c88) cde

    Here the data is not overwritten: a new array is used each time.

    This seems to emulate what is going on in your code.

    It's difficult to be sure exactly what's going on here as you've shown insufficent code and no output.

    Given that your description and your code appear to be at odds with each other, I wonder whether you updated one without updating the other.

    -- Ken

Re: How to create an anonymous array for lines in a file and store a reference to that array in the hash
by happy.barney (Friar) on Oct 29, 2010 at 06:35 UTC
    if i understood correctly, you want something like this ... :-)
    %Hash_filenames = map { chomp; local @ARGV = ($_); ($_ => [<>]) } @plf_files;
Re: How to create an anonymous array for lines in a file and store a reference to that array in the hash
by Anonymous Monk on Oct 29, 2010 at 06:39 UTC
    ow to create an anonymous array for each line and store a reference to that array in the hash?

    Anonymous arrays are created with [ ], see perlref

    But there is no need to do that, the problem you describe does not happen

    my %hash; for my $eye ( 0 .. 2 ){ my @file_lines = map { "$eye$_" } 'a'..'c'; $hash{$eye} = \@file_lines; } use Data::Dumper; print Dumper( \%hash ); __END__ $VAR1 = { '1' => [ '1a', '1b', '1c' ], '0' => [ '0a', '0b', '0c' ], '2' => [ '2a', '2b', '2c' ] };
Re: How to create an anonymous array for lines in a file and store a reference to that array in the hash
by locked_user sundialsvc4 (Abbot) on Nov 01, 2010 at 19:33 UTC

    You are absolutely correct that you can very easily create “a whole bunch of separate references to the same thing,” instead of references to different things.

    “Holy EQUIVALENCE, Captain Fortran!”

    I confess that I sometimes use the Storable module (or nowadays, Clone to explicitly create a “carbon copy” of whatever I need to be damm sure is a unique copy of a thing.   So, I might say... push @myarray, dclone($foobar).  It might not be “efficient,” but generally that is not so important to me as “obvious reliability.”

    P.S.:   As you play “data-structure games,” be mindful of the weaken subroutine in Scalar::Util.   If you might be constructing circular-references between data structures, be certain that one or more of the references are “weakened” so that all of the self-referential data structures eventually will be garbage-collected.