Re: Dereferencing Hash of Arrays



Jennifer I. Drake wrote:
I do have a the 'my ($keysRef) = @_' in my code. I tried to remove
some of the code to be more clear. I guess it has the opposite effect.
The rest of the code is quite long and contains a lot of
CGI/PostgreSQL calls that don't do anything with this issue, so I
wasn't sure if I should post all of it.

You were right to be weary about that. What you *should* have done was
created a *short* but still complete script that demonstrates your
error. That is, par your code down, removing the bits that aren't
relevant to the problem at hand, until you are left with a short script
that someone can run by copy and pasting which still demonstrates your
error.

Please read the Posting Guidelines that are posted here twice a week.
They contain valuable information that will help you get the most help
out of this newsgroup.

###############################################
sub GetData{
###############################################

my ($keysRef, $exptIDsRef, $IDToNameRef, $keyToSUIDRef, $SUIDToKeyRef,
$where, $join, $from, $coordsRef, $retrieveBy, $selectedColumn,
$joinHashRef) = @_;

my $exptnum = scalar(@$exptIDsRef);

print "Using ", font({-color=>'red'}, "$exptnum"), " experiments and
retrieving from the ", font({-color=>'red'}, "Result"), " table for
each experiment\n", p;

my ($exptname, $exptid, $seqname);
my ($key, $spot, $suid, $val, $sth, @values, $keyOffset, %data);

I'm willing to bet this is your central problem. A good general rule
is to always declare variables in the shortest scope possible.

my $count = 1;

my $select = "SELECT RESULT.SPOT, RESULT.LOG_RAT2N_MEAN,
RESULT.CH1I_MEAN ";

$from =~ s/, $//;

my %reverseExpts;
&selectReverse($exptIDsRef, \%reverseExpts);

Why are you prepending your subroutine calls with the ampersand? Do
you know what two side effects that produces? If not, you shouldn't be
using it.

my $reverseFlag = $query->param('isReverse');

my $sql = "$select $from $join AND exptid = ? $where $selectedColumn
IS NOT NULL";

my $sth = $dbh->prepare($sql);

print "Retrieving data...\n<br>";

#print "SQL Statement: $sql<br>";
eval {
foreach $exptid (@{$exptIDsRef}) {

print "$count: $$IDToNameRef{$exptid}",br;

print "Experiment ID: $exptid<br>";
$sth->execute($exptid);

while(($spot, @values) = $sth->fetchrow_array) {

Here you're re-assigning @values each time through your loop, but
you're not re-*declaring* it. That is, you're re-using the same
variable each time through...

if (($reverseFlag eq 'Y' && $reverseExpts{$exptid} eq 'N') ||
($reverseFlag eq 'N' && $reverseExpts{$exptid} eq 'Y')) {
for (my $i = 0; $i < scalar(@values); $i++) {
$values[$i] = -$values[$i];
}
}

Er, what's the point of this? Are you really just trying to make every
value in the array it's opposite? That's really so verbose as to be
difficult to read. Try:

$_ *= -1 for @values;



$$keysRef{$spot} = 1;
$data{$spot}{$exptid} = \@values;

....and here, you're storing multiple references to that same variable
at different points in your structure. So every time you changed the
contents of @values above, you changed the values previously stored in
your overall structure. Change that while loop to:
while (my ($spot, @values) = $sth->fetchrow_array) {


}

if ((!($count%$numToDump)) || ($count==$exptnum)) {
print "Caching data to disk...\n";

&StoreData(\%data, $count, $exptIDsRef, $IDToNameRef);
undef %data;

Why are you undef'ing %data? If you want %data to go away at this
point so you get a new blank version of it next time through your loop,
then properly scope your variables. Declare `my %data` in the smallest
scope in which it is needed. At the end of that scope, before the next
iteration begins, %data will be destroyed and your next iteration will
create a brand new version of it.


}

$count++;

}
};


print br;

&StitchFilesTogether($exptnum, $keysRef, $exptIDsRef, $IDToNameRef);

return(undef);

}

#########################################################
sub StoreData{
#########################################################

my ($dataRef, $count, $exptIDsRef, $IDToNameRef) = @_;
my ($i, $start, $key, $num);
my %data = %$dataRef;
my $number = int(($count-1)/$numToDump) + 1;
my $filename = $$.".".$number.".tmp";

Gah. Use interpolation to improve readability:

my $filename = "$$.$number.tmp";


I'm *guessing* that @values above was the cause of your error. After
making that change, if you still aren't seeing the results you desire,
please post a *short* but *complete* script that demonstrates the
error, along with your sample input, desired output, and actual output.

Paul Lalli

.



Relevant Pages

  • Re: Perl regularexpression problem with the Input file
    ... You're defining $question within the scope of a single iteration of ... the while loop. ... That means as soon as this iteration is done, ... $question goes out of scope. ...
    (comp.lang.perl.misc)
  • Re: Unsure about Something
    ... In the second case you declare a *new* variable in each iteration. ... Because you've gone "out of scope" for the loop, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: execution time slows down the longer the run time
    ... the scope on every iteration of the loop. ... data through a Queue. ...
    (comp.lang.labview)
  • Re: Dereferencing Hash of Arrays
    ... then properly scope your variables. ... iteration begins, %data will be destroyed and your next iteration will ... Nothing happens at the end of a loop body ...
    (comp.lang.perl.misc)
  • Re: About String
    ... My idea is that every statement list is a scope. ... You declare something inside a loop body, ... The same sense as declare blocks. ... SCOPE [DECLS] STATEMENTS END-SCOPE ...
    (comp.lang.ada)