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

I'm trying to create a module that has a hashref as a data member. It appears to function correctly in the same method its initialized in (new) but when I reference it later in another function (test) I get "is not a HASH ref." In the test() method, if I Data::Dumper($self), I can see the hash inside(data), but I can't access $self->{data} directly. here is the module:
package Foo; use strict; use Data::Dumper; use Exporter; our ($VERSION,@ISA,@EXPORT,@EXPORT_OK); $VERSION = 0.99; @ISA = qw(Exporter); @EXPORT = @EXPORT_OK; @EXPORT_OK = qw(new test); sub new(){ my $self = {}; $self->{data} = {}; $self->{data}->{start_url} = "https://www.w.com/home.html"; bless \$self; } sub test(){ my $self = shift; # print $self->{data}->{start_url}; # print Dumper($self); print Dumper($self->{data}); }
and here is the simple test program:
use strict; use warnings; use Foo; my $obj = Foo->new(); $obj->test();
and here is the error: Not a HASH reference at Foo.pm line 26.

Replies are listed 'Best First'.
Re: hash "member" of a module
by Corion (Patriarch) on Apr 15, 2009 at 18:06 UTC
    bless \$self;

    Here, you're blessing a reference to a hash reference. You want to bless the hash reference instead:

    bless $self;

    Also, you will likely want to make your class subclassable, so use the two-argument form of bless:

    sub new { my ($class) = @_; my $self = {}; $self->{data} = {}; $self->{data}->{start_url} = "https://www.w.com/home.html"; bless $self, $class; }

    Also, I've removed the parentheses from the subroutine declaration, as methods ignore any declared prototypes.

Re: hash "member" of a module
by kennethk (Abbot) on Apr 15, 2009 at 18:07 UTC
    That's because you are not returning a hash reference from your function. Within new, $self is a hash reference. When you return \$self, you return a reference to the hash reference, which is a scalar reference. See perlref or perlreftut. The following code works.

    package Foo; use strict; use Data::Dumper; use Exporter; our ($VERSION,@ISA,@EXPORT,@EXPORT_OK); $VERSION = 0.99; @ISA = qw(Exporter); @EXPORT = @EXPORT_OK; @EXPORT_OK = qw(new test); sub new(){ my $self = {}; $self->{data} = {}; $self->{data}->{start_url} = "https://www.w.com/home.html"; bless $self; } sub test(){ my $self = shift; # print $self->{data}->{start_url}; # print Dumper($self); print Dumper($self->{data}); }

    and

    use strict; use warnings; use Foo; my $obj = Foo->new(); $obj->test();
      How silly of me, thank you monks.