How does Perl variable scope work in while loop under strict mode?
I'm ve开发者_JAVA技巧ry new to Perl and I'm confused with exactly how its variable scope works. I'm trying to create an array of Hashes from the result of a MySQL query.
The following code works, as intended, without use strict
my %hash = ();
while (my %hash = %{$qhand->fetchrow_hashref()} ) {
push(@results, {%hash});
}
but when strict is enabled it produces the following error:
Can't use an undefined value as a HASH reference at [filename] line XX (the line of the while statement).
Could someone tell me what I'm doing wrong and what the corresponding rule in strict is that I'm flaunting?
You're violating the refs
portion of strict. When you try to use a non-reference value as a reference, Perl wants to create a "symbolic reference", which is usually not what you want although it silently continues the program (probably not "working", but just continuing). By enabling strictures, you catch those cases.
In your example and Jonathan's answer, it looks like you are doing a lot of acrobatics to undo hash references just to make them hash references again. Is there a reason you don't just leave it as a hash reference?
while( my $href = $qhand->fetchrow_hashref ) {
push @results, $href;
}
And, if you just want to get all the results as hash references, there's a DBI method for that so you can skip the while
loop:
my $results_array_ref = $qhand->fetchall_arrayref( {} );
That's a run time error (after the script has been working for a while), rather than a compile time error, isn't it?
You need to check that the hash ref returned from $qhand->fetchrow_hashref()
(from Perl DBI) is valid before converting the hash ref into a hash. When there are no more rows to fetch, you get back an undef
, and you can't convert the undef
into %hash
.
You also don't want two hashes called %hash
- either in the loop or not in the loop, but not both.
while (my $href = $qhand->fetchrow_hashref())
{
my %hash = %{$href};
push(@results, {%hash});
}
I just ran into the same problem so here was the solution I implemented.
my %rtn;
my $hr = $handle->fetchrow_hashref;
if($hr)
{
do
{
%rtn=%{$hr};
...snip...
...snip...
$hr = $handle->fetchrow_hashref;
}
while ($hr);
}
Set a scalar ($hr) to the expected reference ($handle->fetchrow_hashref) to test for null (if($hr)) before looping and prior to the cast (%{}), then after done with that reference fetch the next one. Once it ends up being null on the next fetch call that breaks the loop and you carry on with no worries.
I'm not a Perl expert, but it's probably the cast to hash on the function call $qhand->fetchrow_hashref()
.
If this function already returns a hash, why not just skip the cast?
精彩评论