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
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 | [reply] [d/l] [select] |
|
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
| [reply] [d/l] [select] |
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)
| [reply] [d/l] [select] |
|
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
| [reply] [d/l] [select] |
|
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.
| [reply] |
Re: Hash references moving between modules
by scain (Curate) on Jan 10, 2003 at 18:22 UTC
|
| [reply] |
|
|