Pergunta

Eu estava lutando com alguns Perl que as referências usos hash.

No final descobriu-se que o meu problema era a linha:

$myhash{$key} |= {};

Isto é, "atribuir R $ myhash {$ key} uma referência a um hash vazio, a menos que já tem um valor".

Dereferencing isso e tentar usá-lo como uma referência de hash, no entanto, resultou em erros de intérprete sobre o uso de uma corda como uma referência hash.

alterá-lo para:

if( ! exists $myhash{$key}) {
  $myhash{$key} = {};
}

... fez coisas trabalho.

Então, eu não tenho um problema . Mas estou curioso sobre o que estava acontecendo.

Alguém pode explicar?

Foi útil?

Solução

A razão que você está vendo um erro sobre o uso de uma corda como uma referência hash é porque você está usando o operador errado. meios |= "bitwise-or-Atribuir." Em outras palavras,

  $foo |= $bar;

é o mesmo que

  $foo = $foo | $bar

O que está acontecendo no seu exemplo é que a sua nova referência de hash anônimo está ficando Stringified, em seguida, bit a bit-ORed com o valor de $myhash{$key}. Para confundir ainda mais as coisas, se $myhash{$key} é indefinido no momento, o valor é o simples stringification da referência do hash, que parece HASH(0x80fc284). Então, se você fizer uma inspecção rápida da estrutura, pode olhar como uma referência de hash, mas não é. Está aqui alguma saída útil via Data::Dumper:

   perl -MData::Dumper -le '$hash{foo} |= { }; print Dumper \%hash'
   $VAR1 = {
             'foo' => 'HASH(0x80fc284)'
           };

E aqui está o que você começa quando você usar o operador correto:

  perl -MData::Dumper -le '$hash{foo} ||= { }; print Dumper \%hash'
  $VAR1 = {
            'foo' => {}
          };

Outras dicas

Perl tem operadores de atribuição de taquigrafia. O operador ||= é frequentemente usado para valores padrão definidos para as variáveis ??devido à característica de ter operadores lógicos retornar o último valor avaliado do Perl. O problema é que você usou |= que é uma bit a bit ou em vez de ||= que é uma lógica ou.

Como de Perl 5.10 é melhor uso //= vez. // é a lógica definida pelo ou do operador e não falha no caso canto onde o valor atual está definido, mas falsa.

Eu acho que o problema estava usando "|=" (bit a bit-ou cessão) em vez de "||=" (Atribuir se falso).

Note que o novo código não é exatamente equivalente. A diferença é que "$myhash{$key} ||= {}" irá substituir valores existentes-mas-falsas com uma referência de hash, mas o novo não. Na prática, isso provavelmente não é relevante.

Tente isto:

my %myhash;
$myhash{$key} ||= {};

Você não pode declarar um hash elemento em uma cláusula my, tanto quanto eu sei. Você declara o hash em primeiro lugar, em seguida, adicionar o elemento.

Edit: Eu vejo que você tenha tomado a my. Que tal experimentar ||= vez de |=? O primeiro é idiomática para inicialização "preguiçoso".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top