Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Need help understanding variable scope in modules

by nysus (Parson)
on Jul 11, 2001 at 22:23 UTC ( #95789=perlquestion: print w/replies, xml ) Need Help??

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

In the following AUTOLOAD subroutine contained in an OO module:
sub AUTOLOAD { my ($self) = @_; $AUTOLOAD =~ /.*::get(_\w+)/ or croak "No such method: $AUTOLOAD"; $self->_accessible($1) or croak "No such attribute: $1"; $self->{_read_count}++; return $self->{$1} }
...I'm wondering why the "_accessible" subroutine needs to be called with $self-> in front of it. In other words, why does plain old
_accessible($1) or croak...
yield an "unitialized value" warning and then croak the program even with a valid public method? Here's the block containing the "_accessible" subroutine:
{ my %_attrs = ( _name => undef, _artist => undef, ); sub _accessible { exists $_attrs{$_[1]}} }
Doesn't the %attrs hash stay alive after leaving the scope because it is referenced in the _accessible subroutine? And what exactly does putting the $self-> in front of the subroutine do differently to prevent the error? Thanks.

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop";
$nysus = $PM . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
(tye)Re: Need help understanding variable scope in modules
by tye (Sage) on Jul 11, 2001 at 22:41 UTC

    You could call it via _accessible( $self, $1 ) where you can even replace $self with any single scalar. The reason you get "undefined value" is that _accessible( $1 ) sets @_ to only contain a single value so that $_[1] is undef.

            - tye (but my friends call me "Tye")
      But if you call it like a regular call, it would break down if you use inheritance.
      $self -> _accessable ($1);
      will search the inheritance tree for the function called _accessable while
      _accessable ($self, $1);
      will call AUTOLOAD if the function was inherited.

      -- Abigail

        Though a roundabout way to accomplish the desired goal would be (with the questionable bonus of making sure '_accessable' is a valid method):
        my $cref = $self->can('_accessable') or croak "Nothing is accessable!"; $cref->($self, $1) or croak "No such attribute: $1";

        Good point. With the function defined within the module (as is implied), I thought that inheritance would not matter. But if AUTOLOAD gets inherited, then the parent class's AUTOLOAD might want to call the child class's _accessible. I just checked and AUTOLOAD does get inherited in 5.6 (I have vague memories of something about this being considered as a bug and can see inherited AUTOLOAD causing some surprises but can also see uses for it so I wasn't sure what the current state was).

        Anyway, I thought that the question implied that inheritance wasn't desired or I would have mentioned it. But thinking on it more, I wouldn't be surprised if that AUTOLOAD was designed to be inherited as part of a technique for inheriting member data.

        Thanks for the catch.

                - tye (but my friends call me "Tye")
Re: Need help understanding variable scope in modules
by japhy (Canon) on Jul 11, 2001 at 22:31 UTC
    The _accessible() function is an object method. It could be different for different objects. It basically ignores the actual object sent to it, and checks to see if the second argument ($1) is a key in a hash that only that function can see.

    japhy -- Perl and Regex Hacker
      I don't see how it could be different for different objects. Here is the structure of the module (from Conway's book):
      use strict; use warnings; package Music; use Carp; our $AUTOLOAD; { my %_attrs = ( _name => undef, _artist => undef, _publisher => undef, _ISBN => undef, _tracks => undef, _rating => undef, _room => undef, _shelf => undef, ); sub _accessible { exists $_attrs{$_[1]}} } { my $_count = 0; # These are class methods. sub get_count { $_count } # This method is global t +o the program my $_incr_count = sub { ++$_count }; sub new # Constructor called "new" { my ($class) = @_; # Gets class passed to co +nstructor $_incr_count->(); bless { # Creates a blessed referen +ce... _name => $_[1], # _artist => $_[2], # _publisher => $_[3], # _ISBN => $_[4], # _tracks => $_[5], # Simply assigns hash +key variables to _room => $_[6], # the arguments passed t +o the constructor. _shelf => $_[7], # _rating => $_[8], # _read_count => 0, }, $class; # in this class } } sub AUTOLOAD { my ($self) = @_; $AUTOLOAD =~ /.*::get(_\w+)/ or croak "No such method: $AUTOLOAD"; $self->_accessible($1) or croak "No such attribute: $1"; $self->{_read_count}++; return $self->{$1} } sub get_location {($_[0]->{_room}, $_[0]->{_shelf}) } sub set_location { my ($self, $shelf, $room) = @_; $self->{_room} = $room; $self->{_shelf} = $shelf; } sub set_rating { my ($self, $rating) = @_; $self->{_rating} = $rating; } 1;

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop";
      $nysus = $PM . $MCF;
      Click here if you love Perl Monks

        Inheritance.
        package Person; sub eat { ... } sub drink { ... } package Alcoholic; @ISA = qw( Person ); sub drink { ... }
        Here, an Alcoholic object has its own drink method, but it inherits the eat method from Person. Similarly, something that inherits from the class you've posted could have its own _accessible method.

        japhy -- Perl and Regex Hacker

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (10)
As of 2021-05-12 13:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Perl 7 will be out ...





    Results (128 votes). Check out past polls.

    Notices?