Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

HTML::LinkExtor weirdness

by skazat (Chaplain)
on Nov 06, 2013 at 20:51 UTC ( [id://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="http://example1.com/"> Example 1 </a> </p> <p> <a href="http://example2.com/"> Example 2 </a> </p> <p> <a href="http://example3.com/"> 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?

-skazat

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 ;)

      -skazat

        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?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (5)
As of 2024-03-28 13:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found