Did I miss-apply what you were trying to say?
Yes.
Change "ok" to {}, and that should work.
while ($book_id = $sth->fetchrow_array()) {
$booklist_1{$book_id} = {};
}
Even then, I urge you to Use strict and warnings. It would have saved you from creating this problem in the first place. Instead of silently doing what you didn't want, it would have told you on its death bed,
Can't use string ("1") as a HASH ref while "strict refs" in use
It's not the best error message in this case, but it would have served better than the mystery you had. If you'd not been able to figure it out, you could have posted it here, and we would have been able to answer immediately rather than groping around.
So I say a third time, Use strict and warnings | [reply] [d/l] [select] |
Oh I agree about strict and warnings - but, frankly, I'm not sure that warning would have helped alot. 'Cause if the problem is that the " = 1" in
while ($book_id = $sth->fetchrow_array()) {
$booklist_1{$book_id} = 1;
}
creates a reference to %1, then why doesn't using something other than "1" correct the problem?
I mean, I just want to set the value of a hash element to one.
I love Perl - it's responsible for most of my personal income and written into most of my work by choice - so don't get me wrong on this next statement - but on a rare occasion Perl does really make me shake my head. It's not like I'm trying to invent calculus here. I just want to set the value of a hash element to 1 then recall the key. It shouldn't take strict and warnings and an in-depth discussion of special variables and references and most of the afternoon...this sort of thing is just ammunition for the anti-Perl crowd...ok, venting off...
By the way, using {} did make the script work correctly, with the sole exception that now $booklist_1{$book_id} equals 'HASH(0x8529f88)' - which is not a problem, per se, since I don't use it, but it seems a very messy result.
Time flies like an arrow. Fruit flies like a banana.
| [reply] [d/l] |
Look in perlref under "symbolic references" for the official scoop, but here's a brief tutorial.
The values in a hash are all scalars. You cannot store a hash in a hash. $h{key} is always a simple scalar value. A reference, however, is also a scalar, so you can store a reference to a hash in a hash.
When you say $h{key}{subkey}, the $h{key} in that expression has to be a reference to a hash. If it turns out that it's a reference to an array, for example, you'll get an error.
When you set $b{$bid} = 'foo' and then say $b{$bid}{'blah'} = 'hahaha', that treats $b{$bid} as a reference. It's a reference to a hash named %foo because $b{$bid} has the value "foo".
So, when you went from using "1" to using "ok", you went from putting everything in %1 to putting everything in %ok. You have the same problem by a different name.
If, as you write in Re^7: Why is my code assigning the last-retrieved value to all elements in my hash?, you set each value to a different string, it "works" because those "references" all go to different hashes.
$b{$bid} = "The Diamond Age";
# $b{$bid}{foo} uses %{"The Diamond Age"}
$b{$bid} = "Snow Crash";
# $b{$bid}{foo} uses %{"Snow Crash"}
$b{$bid} = "b";
# $b{$bid}{foo} pollutes %b directly!
What I've written about mostly so far is just symbolic references. There's another kind, hard references, that don't go around mucking up other variables, because they don't refer to other variables.
$b{$bid} = {};
That creates a hard reference to an anonymous hash. You can then use $b{$bid} to refer to the (anonymous) hash, and it won't destroy other variables willy nilly.
I hope this clears up what's going on with your code.
I've suggested several times that you use strict. I suggest this because it prevents you from using symbolic references. Any attempt to use a string as a reference will cause a fatal error. It also forces you to use my to declare your variables (or refer to them explicitly as package variables), which is another good thing.
There's one other misconception you seem to have that I'd like to clear up. You can't have a $b{foo}{bar} and have $b{foo} set to some unrelated value (such as 1). If there is a $b{foo}{bar}, then $b{foo} must somehow be a reference to a hash where you access ->{bar}. In your original code, that "reference" was "1", treated as a symbolic reference to %1. In the code I suggested, it's a hard reference to an anonymous hash that gets printed as 'HASH(0x8529f88)'. | [reply] [d/l] [select] |
Oh I agree about strict and warnings - but, frankly, I'm not sure that warning would have helped alot.
You don't have to be sure, you do have to act :)
| [reply] |
So here's the truly bizarre part: Changing the hash populating routine to this
$sql = "SELECT book_id, title FROM booklist_table WHERE (expected_publ
+cn_date >= '".$start_date."' AND expected_publcn_date <= '".$end_date
+."')";
$sth = $dbh->prepare($sql) or die("Could not prepare!" . $dbh->errstr)
+;
$sth->execute() or die("Could not execute!" . $dbh->errstr);
while (($book_id, $title) = $sth->fetchrow_array()) {
$booklist_1{$book_id} = $title;
}
$sth->finish;
makes it all work perfectly.
Changing just one line of the above code to
$booklist_1{$book_id} = "ok";
makes it revert to the original incorrect behaviour.
Time flies like an arrow. Fruit flies like a banana.
| [reply] [d/l] [select] |