Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

HTML::LinkExtor weirdness

by skazat (Chaplain)
on Nov 06, 2013 at 20:51 UTC ( #1061477=perlquestion: print w/replies, xml ) Need Help??

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

Observe the following code:

#!/usr/bin/perl use strict; use HTML::LinkExtor; my $html = <<EOF <p> <a href=""> Example 1 </a> </p> <p> <a href=""> Example 2 </a> </p> <p> <a href=""> Example 3 </a> </p> EOF ; # Print them out print "Here's all links:\n"; my @return = find_my_links($html); print join("\n", @return), "\n"; print "Here's all links #2:\n"; my @return2 = find_my_links($html); print join("\n", @return2), "\n"; sub find_my_links { my $str = shift; my @links = (); sub callback { my($tag, %attr) = @_; return if $tag ne 'a'; # we only look closer at <a ...> my $link = $attr{href}; push(@links, $link); } my $p = HTML::LinkExtor->new(\&callback); $p->parse($str); undef $p; undef $str; return @links; }

In this barebones example, I want to grab the links in found in $str, and I encapsulate all my stuff in the find_my_links() subroutine.

Easy enough, and it works! Once. If I call the parse() method twice, the second time will return an empty list. Why?


Replies are listed 'Best First'.
Re: HTML::LinkExtor weirdness (scoping closures nested named subs)
by Anonymous Monk on Nov 06, 2013 at 21:26 UTC

      Indeed, that change doe make things work! Is there somewhere I an further read to understand where I went wrong?

      Infinitely grateful for your help - that darn thing was giving me public fits ;)


        The error message Variable "%s" will not stay shared is described in perldiag. The description is brief but explains the behavior you experienced. You can also read about closure in perlref, perlsub and elsewhere.

        This is why you don't nest named subs, the closure becomes "static"

        perl -E " sub f{ my %g; sub g{say \%g; } g(); say \%g; \%g } say f(),$/ for 1 .. 4;"

        perl -E ' sub f{ my %g; sub g{say \%g; } g(); say \%g; \%g } say f(),$/ for 1 .. 4; '

        HASH(0xabd9c4) HASH(0xabd9c4) HASH(0xabd9c4) HASH(0xabd9c4) HASH(0x3f9b6c) HASH(0x3f9b6c) HASH(0xabd9c4) HASH(0x3f9b8c) HASH(0x3f9b8c) HASH(0xabd9c4) HASH(0x3f9b6c) HASH(0x3f9b6c)

        By making the nested subroutine a variable (also known as an anonymous sub), the closure is dynamic

        $ perl -lE " sub f{ my %g; my $g = sub {say \%g; $g{1}++}; $g->(); say \%g; \%g } say f(),$/ for 1 .. 4;"

        HASH(0xabd9d4) HASH(0xabd9d4) HASH(0xabd9d4) HASH(0x3f9b1c) HASH(0x3f9b1c) HASH(0x3f9b1c) HASH(0x99b374) HASH(0x99b374) HASH(0x99b374) HASH(0x99b344) HASH(0x99b344) HASH(0x99b344)
        I linked it already, just follow the linked links :)

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1061477]
Approved by Laurent_R
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2022-01-18 20:11 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (54 votes). Check out past polls.