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

Newbie alert. I have done some admin scripts in perl, but now I'm trying my hand at cgi using HTML::Template. Following the tutorial on the sourceforge site for HTML::Template, I created the following code that is supposed to generate a table from a directory listing. It generates the table just fine, but the content of the table is wrong. If there are N items in the directory, I get N rows with the Nth item repeated in each row.

I am obviously missing something. If you need more of the code, just ask.

...snip... foreach $dir(@dirlist) { my $newdir=($dest."\/".$dir); if (-f $absdir."\/".$dir) { %info=( driver =>"working", filename=> "<a href=\"../drivers$newdir\">$dir</a><BR>", desc =>"working on this, too" ); } else { %info=( driver =>"working", filename =>"<a href=\"/cgi/index.cgi?$newdir\">$dir</a><BR>", desc =>"working on this, too" ); } push(@tmplt_list, \%info); }
Thanks much, and please be gentle :)

Replies are listed 'Best First'.
Re: Hashrefs and arrayrefs
by stephen (Priest) on Apr 19, 2002 at 14:17 UTC

    Your problem is that you are pushing the same variable reference into to list over and over. You need to localize %info with my, like so:

    ...snip... foreach $dir(@dirlist) { my %info; my $newdir=($dest."\/".$dir); if (-f $absdir."\/".$dir) { %info=( driver =>"working", ...snip...
    It's an easy mistake to make... unless you've got use strict running. Turn on use strict. :)

    stephen

Re: Hashrefs and arrayrefs
by kappa (Chaplain) on Apr 19, 2002 at 14:40 UTC
    TMTOWTDI, as usual :) Change this:
    push(@tmplt_list, \%info);
    ...to this:
    push(@tmplt_list, {%info});
    so that you push a reference to a copy of %info, not the real %info which you change on next iteration.
Re: Hashrefs and arrayrefs
by digger (Friar) on Apr 19, 2002 at 15:11 UTC
    As usual TMTOWTDI.
    Both of your suggestions worked.
    I am using strict as well as warnings (part of the code I did not post). The issue was I put the  my %info outside the foreach loop, so it was not localized correctly. Once I moved the %info declaration inside the foreach, presto, it worked. And I understand it.

    To avoid cargo cult programming, I must ask kappa about the syntax of  push(@tmplt_list, {%info});. What does the extra set of braces around %info accomplish?

    Thank you, again

      push(@tmplt_list, {%info}); . What does the extra set of braces around %info accomplish?

      They create a reference to an anonymous hash, that in this case consists of the same elements as the %info hash. In other words: it copies %info to a hash without a name, and returns a reference to it.

      Would you want to reference the original %info (which is more efficient but not always what you want), you would use:

      push @tmplt_list, \%info;

      - Yes, I reinvent wheels.
      - Spam: Visit eurotraQ.