Inherited class methods and special variables

Discussion in 'Perl' started by Jim Schueler, Aug 18, 2004.

  1. Jim Schueler

    Jim Schueler Guest

    Here is some sample code that uses inherited class methods:

    sub parseHTML::docomment {
    my $comment = shift ;
    print $comment, "\n" ;
    }

    sub parseASP::AUTOLOAD {
    use vars qw( $AUTOLOAD ) ;

    my $key = $AUTOLOAD ;
    my $package = __PACKAGE__ ;
    $key =~ s/^${package}::// ;

    eval "parseHTML::$key( \@_ )" ;
    }

    sub parseASP::doParse () {
    ...
    local $/ = undef ;
    $content = []
    $buf = <HTMLFILE> ;
    $buf =~ s|<!--(.*?)-->|'<!-- '.&docomment( $1, $comments ).'-->'|seig ;
    ...
    }

    sub parseASP::docomment {
    my $comment = shift ;
    print $comment, "\n" ;
    }

    &doParse() ;


    The code listed above works fine, outputting each comment of an HTML file.

    If I delete the last function, parseASP::docomment(), then the inherited
    function parseHTML::docomment() should behave identically. However, this
    time, the code outputs a bunch of blank lines.

    My best theory is that the first argument, $1, is passed as a reference to a
    local special variable that goes out of scope. But common sense tells me that
    anything that goes on the stack should still be there when I pull it off.
    Having lost my mind trying to figure this out, any insight or explanation
    would be greatly appreciated.

    -Jim
    Jim Schueler, Aug 18, 2004
    #1
    1. Advertising

  2. Jim Schueler

    Guest

    (Jim Schueler) wrote in message news:<>...
    > Here is some sample code that uses inherited class methods:


    No it does not.

    What you post is code that crys out to be rewritten using method calls
    inheritance but actually uses subroutine call autoloading to fake
    inheritance.

    I may address that in another follow-up.

    But your problem has nothing to do with that.

    > docomment( $1, $comments )


    > My best theory is that the first argument, $1, is passed as a reference to a
    > local special variable that goes out of scope. But common sense tells me that
    > anything that goes on the stack should still be there when I pull it off.
    > Having lost my mind trying to figure this out, any insight or explanation
    > would be greatly appreciated.


    Actually you have not lost your mind. You have in fact got it right
    except that $1 is not a special local variable, it is a special
    _global_ variable.

    I have described this problem a number of times in the newsgroup that
    replaced this one when this one ceased to exist many years ago.

    By passing $1 as a subroutine argument you create an alias to the
    global variable $1. The global variable $1 magically always refers to
    the last regex evaluated in the current or parent stack frames. This
    means the value of $1 changes as you go in and out of scopes but it's
    still the same variable. The solution is never to pass $1 et al to
    subroutines without quoting.

    Regard...

    my $r = \$1;

    'one' =~ /(.*)/;
    print "$1 $$r\n"; # one one
    {
    {
    'two' =~ /(.*)/;
    print "$1 $$r\n"; # two two
    }
    print "$1 $$r\n"; # one one
    }

    As previously mentioned this newsgroup does not exist (see FAQ).
    Please do not start threads here.
    , Aug 19, 2004
    #2
    1. Advertising

  3. Jim Schueler

    Guest

    (Jim Schueler) wrote in message news:<>...
    > Here is some sample code that uses inherited class methods:


    No it does not.

    What you post is code that crys out to be rewritten using method calls
    inheritance but actually uses subroutine call autoloading to fake
    inheritance.

    I may address that in another follow-up.

    I addresses your real problem in my previous follow-up.

    But now I want to talk about something else

    > sub parseASP::AUTOLOAD {
    > use vars qw( $AUTOLOAD ) ;
    >
    > my $key = $AUTOLOAD ;
    > my $package = __PACKAGE__ ;
    > $key =~ s/^${package}::// ;
    >
    > eval "parseHTML::$key( \@_ )" ;
    > }


    Using symbolic references references is usually a bad idea. Using
    eval(STRING) to achieve something that could be achived by symbolic
    references is worse.

    I very much doubt that you really want to leave the package name in
    $key if it is something other than __PACKAGE__. I suspect that either
    this will never happen or you would want to strip the package name
    regardless.

    The code above is confused. Are you expecting __PACKAGE__ to be
    'parseASP'? If so then the explicit package qualifier on the
    subroutine declaration is redundant. If not then it's unlikely that
    the above would work since you'd be looking at the $AUTOLOAD in the
    wrong package.

    package parseASP;
    sub AUTOLOAD {
    my ($key) = our($AUTOLOAD) =~ /([^:]*)$/ or die;
    goto &{"parseHTML::$key"};
    }

    Note - this will still have the problem with $1 mentioned in my other
    follow-up.

    If you can't fix the calling code you can work-around this thus:

    sub AUTOLOAD {
    my ($key) = do { our($AUTOLOAD) =~ /([^:]*)$/ } or die;
    goto &{"parseHTML::$key"};
    }

    Note: as I said before you'd probably be better off using inheritance
    than AUTOLOAD.
    , Aug 20, 2004
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Tron Thomas
    Replies:
    10
    Views:
    1,058
    Tom Widmer
    Nov 10, 2004
  2. Replies:
    4
    Views:
    376
  3. Replies:
    3
    Views:
    85
  4. 7stud --
    Replies:
    11
    Views:
    386
    7stud --
    Nov 9, 2007
  5. Kenneth McDonald
    Replies:
    5
    Views:
    299
    Kenneth McDonald
    Sep 26, 2008
Loading...

Share This Page