Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Hash references moving between modules

by scain (Curate)
on Jan 10, 2003 at 17:14 UTC ( [id://225869]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Fine Monks,

References are giving me a big headache. Every time I think I have them figured out, Perl gently points out that I don't.

So here is the basic question: how do I access a hash that is created in one package and needed in another? It seems like that should be a simple question with a reasonably simple answer, but I keep banging my head up against a wall trying to get it to work. Below I will put trimmed down versions of my packages to illustrate my question more fully.

Package 1:

package Bio::DB::Das::Chado; use strict; use Bio::Root::Root; use vars qw(@ISA); @ISA = qw(Bio::Root::Root); sub new { my $class = shift; my $self = $class->SUPER::new(@_); # do some work here to extract a DBI $hashref my $cvterm_id; # this scalar is going to be a hashref while (my $hashref = $sth->fetchrow_hashref) { $$cvterm_id{$$hashref{termname}} = $$hashref{cvterm_id}; } return bless {dbh => $dbh, cvterm_id => $cvterm_id}, ref $self ||$self; } sub segment { my $self = shift; my ($name,$start,$end,$class,$version) = $self->_rearrange([qw(NAME START END CLASS VERSION)],@_); # _rearrange is in Bio::Root::Root; I'm allowed to use it # lets the Segment class handle all the lifting. return $self->Bio::DB::Das::Chado::Segment->new($name,$self,$start,$ +end); } 1;
Package 2:
package Bio::DB::Das::Chado::Segment; use strict; use Bio::Root::Root; use vars '@ISA'; @ISA = qw(Bio::Root::Root); sub new { my $self = shift; my ($name,$dbadaptor,$start,$end) = @_; #$dbadaptor is 'Bio::DB::Das::Chado' # now do all kinds of work validating and obtaining info my $cvterm_id = $dbadaptor->{cvterm_id}; # so $cvterm_id should be a reference to the same # hash referenced in the first package, right? return bless {dbadaptor => $dbadaptor, start => $start, end => $end, length => $length, srcfeature_id => $srcfeature_id, cvterm_id => $cvterm_id, name => $name }, ref $self ||$self; } sub features { my $self = shift; # do lots more stuff, mostly to build a sql query my %termhash = %{$self->{cvterm_id}}; # shouldn't this be a reference to the hash ref in this #package's constructor, that in turn is a ref to the # hash ref in the first package? my @keys = grep(/\sgene/i , keys %termhash ); # this fails because %termhash isn't a hash. return; } 1;
Any pointers would be appreciated. Thanks for looking through this code; I hope I usefully trimmed it down.
Thanks,

Scott
Project coordinator of the Generic Model Organism Database Project

Replies are listed 'Best First'.
Re: Hash references moving between modules
by derby (Abbot) on Jan 10, 2003 at 17:59 UTC
    For starters, I don't understand both Bio:DB::Das::Chado and Bio::DB::Das::Chado::Segment being subclasses of Bio::Root::Root ... but besides that I also don't think this line is doing what you want:

    return $self->Bio::DB::Das::Chado::Segment->new($name,$self,$start,$end);

    shouldn't that just be:

    return Bio::DB::Das::Chado::Segment->new($name,$self,$start,$end);

    Other than that, are you sure your sql is returning results? If your sql fails, $cvterm_id will never be converted to a hash reference (it will stay a plain scalar) and your code downstream will fail. You probably want something like this to protect the code downstream (or you could check if you have a hash downline):

    my $cvterm_id = {} ; # this scalar is a hashref while (my $hashref = $sth->fetchrow_hashref) { $$cvterm_id{$$hashref{termname}} = $$hashref{cvterm_id}; }

    Then at least %termhash will be a hash but quite possibly an empty one if the sql fails.

    -derby

      Ack, that is what I get for trying to simplify too much. First, Bio::Root::Root is the main class from which most BioPerl objects inherit.

      The first line you mention didn't really look like that in my code, it was

      return $self->_segclass->new($name,$self,$start,$end);
      Where _segclass is a private method that returns the string 'Bio::DB::Das::Chado::Segment'. I was trying to hard to trim things down and simplified one thing to make it wrong.

      It is a good point that I should be checking for returned results. In this case, I know that they are from previous debugging. Nevertheless, I will add the = {}; because that is a good idea.

      Thanks,

      Scott
      Project coordinator of the Generic Model Organism Database Project

Re: Hash references moving between modules
by castaway (Parson) on Jan 10, 2003 at 18:36 UTC
    Hi,
    I don't think your $cvterm_id holds what you think it does at all.
    my $cvterm_id; # this scalar is going to be a hashref while (my $hashref = $sth->fetchrow_hashref) { $$cvterm_id{$$hashref{termname}} = $$hashref{cvterm_id}; }
    $cvterm_id is a scalar with no content at the beginning.
    You get a $hashref from somewhere.
    "$$hashref{cvterm_id}" is extracting the item called 'cvterm_id' from a hash called whatever is in $hashref. Eg. if $hashref = 'fred' then it's looking at element 'cvterm_id' in %fred. I'm not sure thats what you want.
    Likewise the result is being written into a hash with no name (as $cvterm_id is undefined, no idea what that actually does..), in the element called $fred{termname}

    If $cvterm_id is going to be a hash reference, you need to use it like this:

    my $cvterm_id; # this scalar is going to be a hashref while (my $hashref = $sth->fetchrow_hashref) { $cvterm_id->{$$hashref{termname}} = $$hashref{cvterm_id}; }
    If $hashref is also a real hash reference and not just the name of a hash, then you need this:
    my $cvterm_id; # this scalar is going to be a hashref while (my $hashref = $sth->fetchrow_hashref) { $cvterm_id->{$hashref->{termname}} = $hashref->{cvterm_id}; }
    Then the second package should work.

    Try looking at the contents of $cvterm_id in the second package after the while loop, using Data::Dumper for instance. (use Data::Dumper; print Dumper($cvterm_id);)
    I hope that helps,
    C.
    PS: Dereferencing references using the arrow operator is explained on page 253 of the Camel book (3rd edition)

      Hmm... Well, derefrencing a hashref can be done in the way you showed up there, but it is perfectly valid to get a scalar back from a hashref this way as well:
      $scalar = $$hashref{key};
      and assigning into a hashref can be done in the same way:
      my $hashref = {}; $$hashref{key} = $scalar;
      Perhaps taking a look at References quick reference will sum it up nicely.

      Thanks,

      Scott
      Project coordinator of the Generic Model Organism Database Project

        Thanks,
        I noticed that a while after I wrote it. I guess I'm too used to using ->.. I think thats more readable than $$ ..
        C.
Re: Hash references moving between modules
by scain (Curate) on Jan 10, 2003 at 18:22 UTC
    Turns out this was a trick question--the thing that I thought was a hashref really was. It was the next line with the grep that was failing. That regex should have been /^gene/ instead. As a result, the @keys array was empty, making it look later on like I didn't having anything in the hash.

    D'oh!

    Thanks anyway,

    Scott
    Project coordinator of the Generic Model Organism Database Project

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2024-03-29 12:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found