perl-diddler has asked for the wisdom of the Perl Monks concerning the following question:

I'm parsing HTML. At each tag level, I want to store some variables (tag, print, class, id, defines_class, defines_id).

I'm using HTML::parser which calls a 'start' routine for each start of a tag. Tags are all closed with a call to an 'end' routine (real or simulated for self-closing tags).

So what I'd *like* to do in my parse structure, is to allocate an array for the local vars and alias *names* to the array members for processing in a given 'frame'...like:

my @local_vars; $#local_vars=5; #(don't like the literal 5, but haven' +t gotten so far as to worry about that yet) push @{$this}->{local_vars}}, \@local_vars; #create space for this ta +g's vars assign_names(qw (open_tag, tagprint, cur_class, cur_id, defines_class, + defines_id), \@local_vars); ## this is the questionable 'magic' part +... # now...can use names as one would use local vars.... if ($open_tag eq 'div' and $cur_class eq 'pager') {...
Is this hopelessly idealistic, or is this doable? I figure it's *probably* possible if I was willing to assign to each name something like \$local_vars[0], \$local_vars1... and then use the names with double dollar signs, but I wanted to avoid the ugliness...

Replies are listed 'Best First'.
Re: possible to assign symbolic references?
by ikegami (Patriarch) on Sep 21, 2010 at 22:59 UTC

    if ($open_tag eq 'div'

    You don't actually use references, symbolic or otherwise. You're asking to create aliases.

    It's actually possible to do what you want without even using Data::Alias.

    push @{ $this->{local_vars} }, sub { \@_ }->(my ( $open_tag, $tagprint, $cur_class, $cur_id, $defines_class, $defines_id, )); ... if ($open_tag eq 'div' and $cur_class eq 'pager') {...

    Of course, it might wiser to actually use references.

    my @local_vars; push @{ $this->{local_vars} }, \@local_vars; my ( $open_tag, $tagprint, $cur_class, $cur_id, $defines_class, $defines_id, ) = \@local_vars[0..5]; ... if ($$open_tag eq 'div' and $$cur_class eq 'pager') {...
      Why would using references be preferable? Is use of Data::aliases expensive (or more so) than using a dereference on each access?

        Aliases would be less expensive once created. However, using aliases introduces more magic (especially if Data::Alias is involved) and creates more action at a distance (making the code less clear and harder to debug).

        Actually, even simpler would be to use neither. The problem only exists because the addition of the scalars to the data structure is done at the top of the code.

        my ($var1, $var2, ...); ... push @array, [ $var1, $var2, ... ];

        The downside is that you might have to guard against exceptions and returns.

        Real references are solid, dependable things.

        Symbolic references are a leap of faith that will kill you eventually.

Re: possible to assign symbolic references?
by Anonymous Monk on Sep 21, 2010 at 23:01 UTC

    If you want names, then you are looking for a hash.

    $currentTag->{class} = 'Widget'; #for exampleYou can then pass $currentTag around, or push it onto an array of children of the parent tag, or whatever you need to do.

    Just say my $currentTag = {}; when you start a new tag, or my %currentTag = (); if you prefer.

    Then you can do push @{$parentTag->{children}}, $currentTag; or push @{$parentTag{children}}, \%currentTag; respectively.

      Yeah, I agree. Whenever I want names like this I just resort to hashes. They are easy to understand for just about anyone who reads the code and do not introduce any special magic that will eventually come back to bite you.

      Elda Taluta; Sarks Sark; Ark Arks