Será que uma chave de hash não inicializado tem um valor padrão de zero em Perl?

StackOverflow https://stackoverflow.com/questions/811515

  •  03-07-2019
  •  | 
  •  

Pergunta

Eu tenho o código Perl semelhante ao seguinte:

# -- start --

my $res;

# run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{
    if( $row->[4] =~ /PA/ ) {
        $res->{ipv6}{pa}{$row->[2]}++;
    } elsif( $row->[4] eq 'PI' ) {
        $res->{ipv6}{pi}{$row->[2]}++;
    }
}

# -- stop --

Em nenhum momento é $res já definido antes da iteração sobre os resultados da consulta ainda o código é executado muito bem.

Quando eu coloquei instruções de impressão antes de cada valor eu recebo espaços em branco em ambos os casos, mas se as instruções de impressão vir após o incremento foi aplicado eu recebo um valor> = 1 dependendo de quantos recursos IPv6 a organização tem.

A minha pergunta é, posso levar isto para dizer uma chave de hash não inicializado em Perl automaticamente tem um valor de zero?

Desculpe se ele aparece como uma questão novato, mas eu simplesmente não estou familiarizado com tal construção de um isto é $hashref->{foo}->{bar}++ onde um valor ainda tem de ser explicitamente atribuído a $hashref->{foo}->{bar}. Agradecemos antecipadamente!

Foi útil?

Solução

O valor não é automaticamente zero. O valor é indefinido inicialmente. No entanto, se você tratá-lo como um número (por exemplo, aplicar ++ a ele), então trata Perl-lo como zero. Se você tratá-lo como uma string (por exemplo, aplicar . a ele), então trata Perl-lo como uma string vazia.

De perldoc perlsyn, sob 'declarações':

As únicas coisas que você precisa declarar por Perl são formatos de relatórios e sub-rotinas (e às vezes nem mesmo subrotinas). Uma variável detém o valor indefinido ( "undef") até que ele tem sido atribuído um valor definido, que é algo diferente de "undef". Quando utilizado como um número, "undef" é tratada como 0; quando usado como uma string, é tratada como a cadeia "" vazio; e quando utilizado como uma referência que não é sendo atribuído, que é tratado como um erro.

Outras dicas

Para elaborar pós Telêmaco, os valores não inicializadas será indefinido. As partes profundas da estrutura são autovivified . Este é um recurso útil onde estruturas de dados são criados automaticamente para você. Autovivification é ótimo quando você quer, mas pode ser uma dor quando você quer evitar isso. Existem muitos tutoriais, artigos e posts em torno da rede em autovivification entendimento.

Assim, dado um $ref indefinido e $ref->{ipv6}{pa}{'foo'}++, $ref será atribuído um valor de:

$ref = { 
     ipv6 => { 
          pa => { 
              foo => undef
          }
     }
};

Em seguida, a undef será incrementado, desde numifies undef a 0, obtemos 0 ++ que é 1. Para um resultado final:. ref->{ipv6}{pa}{'foo'} == 1

Se você tem avisos habilitado, (você use warnings;, não é?), Você receberá um "valor não inicializado" aviso quando você opera sobre esses valores indefinidos. Se for o comportamento desejado para incrementar o valor não inicializado, então você pode transformar o grupo desejado de avisos fora sobre uma parte limitada do seu código:

use strict;
use warnings;
my $res;

// run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{   no warnings 'uninitialized';
    if( $row->[4] =~ /PA/ ) {
        $res->{ipv6}{pa}{$row->[2]}++;
    } elsif( $row->[4] eq 'PI' ) {
        $res->{ipv6}{pi}{$row->[2]}++;
    }
}

Você pode encontrar a hierarquia avisos em perllexwarn .

É basicamente indefinido, mas tratado como se fosse zero quando você incrementa-lo.

O termo em Perl linguagem é 'autovivified'.

O que você provavelmente quer fazer é usar a existe palavra-chave :

$res->{ipv6}{pa}{$row->[2]}++ if exists($res->{ipv6}{pa}{$row->[2]});

Não há tal coisa como um hash não inicializado tecla . A única coisa que pode ser inicializado é a valor para uma chave particular. Um valor de hash é apenas um valor escalar; não é diferente do que uma variável como $foo.

Há um par de diferentes Perl características interagindo no seu exemplo.

Inicialmente $res é indefinido (ou seja, ele tem o valor undef). Quando você usa um valor não inicializado como uma referência de hash (como no $res->{ipv6}...) Perl "autovivifies"-lo como um. Ou seja, Perl cria um hash anônimo e substitui o valor de undef com uma referência para o novo hash. Esse processo se repete (silenciosamente) cada vez que você usar o valor resultante como uma referência.

Eventualmente, você autovivify seu caminho para $res->{ipv6}{pa}{$row->[2]}, que é indefinido. Lembre-se que este é apenas um valor escalar como $foo. O comportamento é o mesmo que dizer

my $foo;
$foo++;

Perl faz coisas especiais quando você usa valores indefinidos. Se você usá-los como um número, Perl converte-los a 0. Se você usá-los como uma string, Perl converte-los para '' (uma string vazia). Na maioria dos casos você vai ter um "Uso de valor não inicializado ..." Atenção Se tiver advertências ligadas (que você deve). A operador de auto-incremento (++) é um caso especial, no entanto. Por conveniência, ele silenciosamente converte o valor de undef para 0 antes de incrementá-lo.

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