7

コメントアウトするとDumper($cmd_string)whileループは発生しません。

Dumper()は$ cmd_stringにどのような副作用がありますか?

サブ呼び出しの前の$cmd_stringは次のとおりです。

VAR1 = {
    'The Java Runtime Library' => {
        'apt-get install -y' => 'sun-java6-jre'
    }
};


sub installPackages
{
    my $cmd_string = shift;
    my %rc_hash;

    my $rc;

    Dumper($cmd_string);

    for my $desc (keys %{$cmd_string})
    {
        while (my ($cmd, $arg) = each %{$cmd_string->{$desc}})
        {
            print "system($cmd $arg)\n";

            $rc = system("$cmd $arg");

            if ($rc)
            {
                $rc_hash{$desc}{$cmd} = '';
            }
        }
    }
    return \%rc_hash;
}

Dumper()を使用せずにPerlデバッガーを実行し、$ cmd_stringでxコマンドを使用すると機能しますが、コードをステップ実行するだけでは機能しません。

これは、サブの最後にあるコードをステップスルーした後です

  DB<3> x $cmd_string
0  HASH(0x2769550)
   '' => HASH(0x2769880)
        empty hash
   'The Java Runtime Library' => HASH(0x25cc2a0)
      'apt-get install -y' => 'sun-java6-jre'
  DB<4> x $cmd_string->{$desc}
0  HASH(0x2769880)
     empty hash

ここで、forループの前に$ cmd_stringをxすると、subの最後にこれが表示されます。

main::installPackages(msi.pl:1979):       return \%rc_hash;
  DB<3> x $cmd_string
0  HASH(0x1125490)
   'The Java Runtime Library' => HASH(0xf852a0)
      'apt-get install -y' => 'sun-java6-jre'
4

1 に答える 1

12

イテレータオーバーハッシュは、ハッシュごとに非表示のeach変数を使用して、ハッシュ内のどこにあるかを追跡します。私の推測では、$cmd_stringハッシュの生成に使用されるコードも使用しますeachが、完了まで反復していません。

eachイテレータをリセットするにはkeys %{$cmd_string->{$desc}};、whileループの前に配置します。voidコンテキストでの呼び出しkeysは、ハッシュイテレータをリセットする標準的な方法です。

または、ループ内で変数を使用for my $cmd (keys %{$cmd_string->{$desc}}) {して作成します。$arg

を使用すると問題が修正される理由Dumper()は、Dumperkeysがハッシュを呼び出す可能性が高く、それによってイテレータがリセットされるためです。

于 2011-03-23T21:25:46.483 に答える