in reply to Re: Subroutines with differing behaviour created from AUTOLOAD
in thread Subroutines with differing behaviour created from AUTOLOAD

the methods you are injecting will be closures over the current $self, so it won't work if you have more than one object in the class
Wow, apparently not. Although I realised the subs were closures (by keeping the value $field), I never realised that this would break for more than one object instance.
Does this mean that I should remove the assignment to the symbol table and live with the performance penalty?

davis
It's not easy to juggle a pregnant wife and a troubled child, but somehow I managed to fit in eight hours of TV a day.
  • Comment on Re^2: Subroutines with differing behaviour created from AUTOLOAD

Replies are listed 'Best First'.
Re^3: Subroutines with differing behaviour created from AUTOLOAD
by rinceWind (Monsignor) on Jun 08, 2004 at 14:58 UTC
    This is a case when eval saves the day: (warning untested)
    die "No such method $AUTOLOAD. Barfing\n" unless exists $self->{$field}; if ($self->{$field}{editable}) { *$AUTOLOAD = eval <<ENDSUB; sub { my \$self = shift; \$self->{$field}{value} = shift if \@_; \$self->{$field}{value}; } ENDSUB } else { *$AUTOLOAD = eval <<ENDSUB2; sub { my \$self = shift; die "Can't modify readonly field '$field'" if \@_; \$self->{$field}{value}; } ENDSUB2 } goto &$AUTOLOAD;

    --
    I'm Not Just Another Perl Hacker

      That works (and is pretty damn cool, to boot), but doesn't it also negate the symbol table-insertion techniques? The eval'd code will have to be parsed anew each time the sub is called.

      davis
      It's not easy to juggle a pregnant wife and a troubled child, but somehow I managed to fit in eight hours of TV a day.
        ... but doesn't it also negate the symbol table-insertion techniques? The eval'd code will have to be parsed anew each time the sub is called.
        Not so. The evals return code references which are stuffed into the package symbol table to make accessor methods; a subsequent call to the same method will find it and not call AUTOLOAD.

        The purpose of the eval is to bind $field at the time AUTOLOAD happens. It does this as it is in the string passed to eval without an escape (all other variables are escaped). With the original, $field is not bound to a specific value, but forms a closure, and is bound to the calling pad (hence it will share values between instances). The eval solution gives you a fresh op tree each time AUTOLOAD is called.

        --
        I'm Not Just Another Perl Hacker

Re^3: Subroutines with differing behaviour created from AUTOLOAD
by hv (Prior) on Jun 08, 2004 at 16:19 UTC

    No, it means only that you should declare my $self in the subs you create, as in my example - without such a declaration, the $self in the anonymous subs refers to the closest enclosing declaration (the my $self of the AUTOLOAD routine), and that is what creates the unwanted closure.

    You might prefer to further reduce the potential for confusion by using a different variable name for the two: perhaps by renaming the outer $self to $object or somesuch.

    Hugo