Inherited class methods and special variables

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jim Schueler

    Inherited class methods and special variables

    Here is some sample code that uses inherited class methods:

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

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

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

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

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

    sub parseASP::docom ment {
    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::docom ment(), then the inherited
    function parseHTML::doco mment() 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
  • nobull@mail.com

    #2
    Re: Inherited class methods and special variables

    jschueler@tqis. com (Jim Schueler) wrote in message news:<ad8dc33f. 0408181020.6826 9010@posting.go ogle.com>...[color=blue]
    > Here is some sample code that uses inherited class methods:[/color]

    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.
    [color=blue]
    > docomment( $1, $comments )[/color]
    [color=blue]
    > 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.[/color]

    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.

    Comment

    • nobull@mail.com

      #3
      Re: Inherited class methods and special variables

      jschueler@tqis. com (Jim Schueler) wrote in message news:<ad8dc33f. 0408181020.6826 9010@posting.go ogle.com>...[color=blue]
      > Here is some sample code that uses inherited class methods:[/color]

      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
      [color=blue]
      > sub parseASP::AUTOL OAD {
      > use vars qw( $AUTOLOAD ) ;
      >
      > my $key = $AUTOLOAD ;
      > my $package = __PACKAGE__ ;
      > $key =~ s/^${package}::// ;
      >
      > eval "parseHTML::$ke y( \@_ )" ;
      > }[/color]

      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.

      Comment

      Working...