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

In the article on HTML::Template at http://html-template.sourceforge.net/article.html, there is some sample code:

foreach my $name (sort keys %fruit_data) { # get the color and shape from the data hash my ($color, $shape) = @{$fruit_data{$name}}; # make a new row for this fruit - the keys are <TMPL_VAR> names # and the values are the values to fill in the template. my %row = ( name => $name, color => $color, shape => $shape ); # put this row into the loop by reference push(@loop, \%row); }

... but I'm confused - this looks like (and testing seems to bear it out) that the contents of @loop will all be identical hashes (since they are all references to a single hash, %row).

Here's the code I used to check this:

print "Here we push a hash onto a list, modify the hash and push again +\n"; my @list; my %hash; %hash = ( val1 => 'foo', var2 => 'bar' ); print "contents of \$hash\n"; foreach(keys %hash){ print "$_ = $hash{$_}\n"; } push(@list, \%hash); my $key; print "deref contents of \@list\n"; foreach(@list){ foreach $key(keys %$_){ print "$key = $$_{$key}\n"; } } %hash = ( val1 => 'bish', val2 => 'bash' ); print "contents of \$hash\n"; foreach(keys %hash){ print "$_ = $hash{$_}\n"; } push(@list, \%hash); print "deref contents of \@list\n"; foreach(@list){ foreach $key(keys %$_){ print "$key = $$_{$key}\n"; } }

Is the article wrong, or have I missed something?

Tom Melly, tom@tomandlu.co.uk

Replies are listed 'Best First'.
Re: Confused by reference sample code
by sgifford (Prior) on Mar 28, 2006 at 19:50 UTC
    The key is the my in the sample code. That creates a new variable every time through the loop. Your test uses a global variable instead.

      Many thanks - I must admit that the difference between 'my' inside a loop and outside in this context had elluded me (the distinction between 'new variable' and 'same variable' is somewhat blurred in this context).

      Question: if the memory allocated to the hash had not been passed by ref. to the array, would perl have released it's memory?

      Tom Melly, tom@tomandlu.co.uk
        if the memory allocated to the hash had not been passed by ref. to the array, would perl have released it's memory?

        Yes. Perl uses reference counting to determine if a variable is still in use. As soon as there are no references to a variable, the memory is released back to Perl (but not necessarilly to the operating system). For example,

        { # Creates a scalar with value 'val1'. my $var1 = 'val1'; # 1 reference to val1. } # $var1 goes out of scope. # 0 references to val1. # No more references to 'val1', so it is released. my $var2; { # Creates a scalar with value 'val1'. my $var3 = 'val2'; # 1 reference to val2. $var2 = \$var3; # 2 references to val2. } # $var3 goes out of scope. # 1 reference to val2. $var2 = 'val3' # 0 references to val2. 1 reference to val3. # No more references to 'val2', so it is released.
Re: Confused by reference sample code
by duff (Parson) on Mar 28, 2006 at 19:54 UTC
    .. but I'm confused - this looks like (and testing seems to bear it out) that the contents of @loop will all be identical hashes (since they are all references to a single hash, %row).

    Nope. Your tests are wrong. The original code gets a new %hash on each iteration of the loop since it's declared with my inside the loop. Your test declares a single hash and manipulates the values of that single hash. For the test to be similar to the original code, you'd need to use my on both assignments.

Re: Confused by reference sample code
by InfiniteSilence (Curate) on Mar 28, 2006 at 21:08 UTC
    I read that tutorial and I can see why you are confused. First, check out the HTML::Template perldoc for the section on the TMPL_LOOP tag. It shows the actual structure that is being used for TMPL_LOOP. If you want to use Data::Dumper, you can see it for yourself:
    use Data::Dumper; use CGI qw|:standard|; use HTML::Template; # the fruit data - the keys are the fruit names and the values are # pairs of color and shape contained in anonymous arrays my @loop; my %fruit_data = ( Apple => ['Red, Green or Yellow', 'Round'], Orange => ['Orange', 'Round'], Pear => ['Green or Red', 'Pear-Shaped'], Banana => ['Yellow', 'Curved'], ); print header(); my $tmplObj = HTML::Template->new(filename=>'..\..\tmpl\fruit.tmpl') +; for(keys %fruit_data){ push @loop, {name=>$_, color=>$fruit_data{$_}->[0], shape=>$fruit_data{$_}->[1] }; } my $whatIamReallyPassing = { fruit_loop => \@loop }; warn Dumper $whatIamReallyPassing; $tmplObj->param($whatIamReallyPassing); print $tmplObj->output;

    Celebrate Intellectual Diversity