The author of this module chose to use some file scoped variables in a module. This effectively created some global variables used outside the sub. This is not the recommended way to write a subroutine, but I needed an example and this one was handy. :)

PERL:
  1. my $htmltree;
  2. my $node;
  3. my @prevnodes;
  4. my $htmloutput;
  5.  
  6. sub start {
  7.     my $tagname = shift;
  8.     my $attr = shift;
  9.     my $newnode = {};
  10.  
  11.     $newnode->{tag} = $tagname;
  12.     foreach my $key(keys %{$attr}) {
  13.         $newnode->{$key} = $attr->{$key};
  14.     }
  15.     $newnode->{content} = [];
  16.     push @prevnodes, $node;
  17.     push @{$node}, $newnode;
  18.     $node = $newnode->{content};
  19. }

The author also decided to use a hash reference ($newnode) for the data structure. Had he used a hash instead things might have been simpler. Take a look at the addition of the keys from %{$attr}. This same thing can occur with a hash slice. Let's let an example tell the story.

PERL:
  1. my $newnode = {};
  2.  
  3.     $newnode->{tag} = $tagname;
  4.     foreach my $key(keys %{$attr}) {
  5.         $newnode->{$key} = $attr->{$key};
  6.     }
  7.     $newnode->{content} = [];
  8. }

Could be written as:

PERL:
  1. my %newnode;
  2.  
  3.     $newnode{tag} = $tagname;
  4.     @newnode{ keys %{$attr} } = values %{$attr};
  5.     $newnode{content} = [];
  6. }

Which could be written as:

PERL:
  1. my %newnode = ( tag => $tagname, );
  2.     @newnode{ keys %$attr } = values %$attr;
  3.     $newnode{content} = [];
  4. }

And the whole sub becomes:

PERL:
  1. my $tagname = shift;
  2.     my $attr    = shift;
  3.  
  4.     my %newnode = ( tag => $tagname, );
  5.     @newnode{ keys %$attr } = values %$attr;
  6.     $newnode{content} = [];
  7.  
  8.     push @prevnodes$node;
  9.     push @$node,     %newnode;
  10.  
  11.     $node = $newnode->{content};
  12. }

While keys is not guaranteed to be in the same order each time it is called, it is guaranteed to be in the same order as values as long as no operations to change the hash have occurred.