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

I am working on making a module to test my Perl skills. I am trying to return an object with hashes in it that you can access through the object, but I can't access the hashes.

Here is my code:

return bless { 'hits' => { %hits }, 'hosts' => { %hosts }, 'hitsByDate' => { %hitsByDate }, 'hitsByTime' => { %hitsByTime }, 'hitsByDateTime' => { %hitsByDateTime }, 'visitsByDate' => { %visitsByDate }, 'visitsByTime' => { %visitsByTime }, 'visitsByDateTime' => { %visitsByDateTime }, 'methods' => { %methods }, };


I am calling it like this:
my $al = new Apache::LogParser; my $log = $al->getAccessLog(); my %hits = $log->hits;


The module is Apache::LogParser and the getAccessLog() routines is returing the first section of code with the bless and hashes. The problem is it isn't returning hashes when I call $log->hits amd I can't figure out why.

I've tried returning it without blessing it and many other ways, but it just won't go. Do any monks know what I am missing or am doing wrong. I know the variables are filled because i can print them directly from the module. I just can't seem to get it to work.

Thanks for your time

Replies are listed 'Best First'.
Re: Returning in a module
by borisz (Canon) on Jul 08, 2004 at 21:39 UTC
    Try to use strict; in front of your module. If getAccessLog() returns the hashref, you need to use it like $log->{hits}. Also note, that you should prefer bless with two arguments.
    Boris
Re: Returning in a module
by tachyon (Chancellor) on Jul 08, 2004 at 23:35 UTC

    This should get you started:

    package Apache::LogParser; use Carp; sub new { my ( $class ) = @_; my $self = { hits => { foo => 1, bar => 2 }, misses => { baz => 3, boo => 4 }, }; # we need to bless our hash into our class! return bless $self, $class; } # define an accessor, use wantarray to return hash or hash ref dependi +ng on context sub hits { my ( $self ) = @_; return wantarray ? %{$self->{hits}} : $self->{hits}; } # define a generic accessor using autoload to save lots of accessor co +de # you could also make this a set/get method, it is just a get as shown sub AUTOLOAD { my ( $self ) = @_; my ( $func ) = $AUTOLOAD =~ m/::([^:]+)$/; if ( exists $self->{$func} ) { return wantarray ? %{$self->{$func}} : $self->{$func}; } else { confess "Unknown method $func\n"; } } use Data::Dumper; my $al = new Apache::LogParser; my %hits = $al->hits; print Dumper \%hits; print Dumper scalar($al->misses); $al->no_existing_method;

    cheers

    tachyon

Re: Returning in a module
by ysth (Canon) on Jul 08, 2004 at 22:16 UTC
    If getAccessLog is the sub that has that return statement, $log->{hits} will be a hashref to a copy of your original %hits. You can copy it to another hash like my %hits = %{$log->{hits}};, or just use the hashref in various ways like:
    my $hits = $log->{hits}; print keys %$hits; # print all the keys print "$key => $value\n" while (my ($key, $value) = each %$hits); # du +mp all print $hits->{keyX}; # print one value
Re: Returning in a module
by Mercio (Scribe) on Jul 09, 2004 at 04:07 UTC
    Thanks guys, it's working great now.