Perl变量作用域如何在严格模式下循环工作?

时间:2010-10-07 17:12:05

标签: perl scope

我是Perl的新手,我对其变量范围的工作原理感到困惑。 我正在尝试从MySQL查询的结果创建一个Hashes数组。

以下代码按预期使用不使用使用严格

  my %hash = ();

  while (my %hash = %{$qhand->fetchrow_hashref()} ) {
    push(@results, {%hash});
  }

但启用严格时会产生以下错误:

不能在[filename]第XX行(while语句的行)中使用未定义的值作为HASH引用。

有人可以告诉我,我做错了什么,严格的相应规则是什么,我是炫耀?

4 个答案:

答案 0 :(得分:8)

您违反了strictrefs部分。当您尝试使用非引用值作为引用时,Perl想要创建一个“符号引用”,这通常不是您想要的,尽管它默默地继续程序(可能不是“工作”,而是继续)。通过启用限制,您可以捕获这些情况。

在你的例子和Jonathan的回答中,看起来你正在做很多杂技来撤销哈希引用,只是为了让它们再次成为哈希引用。您是否有理由不将其作为哈希引用?

while( my $href = $qhand->fetchrow_hashref ) {
  push @results, $href;
  }

而且,如果您只想将所有结果作为哈希引用,那么有一个DBI方法,以便您可以跳过while循环:

my $results_array_ref = $qhand->fetchall_arrayref( {} );

答案 1 :(得分:3)

这是一个运行时错误(在脚本工作一段时间后),而不是编译时错误,不是吗?

在将散列引用转换为散列之前,您需要检查从$qhand->fetchrow_hashref()(来自Perl DBI)返回的散列引用是否有效。如果没有其他要提取的行,则会返回undef,而您无法将undef转换为%hash

你也不想要两个名为%hash的哈希 - 无论是在循环中还是不在循环中,而不是两者。

  while (my $href = $qhand->fetchrow_hashref())
  {
      my %hash = %{$href};
      push(@results, {%hash});
  }

答案 2 :(得分:1)

我遇到了同样的问题,所以这是我实施的解决方案。

my %rtn;
my $hr = $handle->fetchrow_hashref;
if($hr)
{
    do
    {
        %rtn=%{$hr};
        ...snip...


        ...snip...
        $hr = $handle->fetchrow_hashref;
    }
    while ($hr);
}

将标量($ hr)设置为预期引用($ handle-> fetchrow_hashref)以在循环之前和转换之前(%{})测试null(if($ hr)),然后完成之后该引用获取下一个。一旦它在下一个打破循环的提取调用中结束为null,你就不用担心了。

答案 3 :(得分:-7)

我不是Perl专家,但它可能是函数调用$qhand->fetchrow_hashref()上的转换。 如果此函数已经返回哈希,为什么不跳过强制转换?