Pergunta

Aqui estão algumas simples Perl para contar o número de vezes que um valor ocorre em uma matriz. Isso executa sem qualquer aviso.

use warnings;
use strict;

my @data = qw(1 1 2 3 4 5 5 5 9);
my %histogram;
foreach (@data)
{
    $histogram{$_}++;
}

Quando o corpo do laço é alterado para

$histogram{$_} = $histogram{$_} + 1;

Perl adverte "Uso de valor não inicializado além".

O que está acontecendo sob o capô? Por que é o valor inicializado quando fornecido como um operando para o operador ++ e inicializado com o operador +?

Foi útil?

Solução

o operador + avalia tanto a forma para a esquerda e o formulário para a direita dele, em seguida, retorna a soma de ambos. A avaliação chamada de hash não vê qualquer contexto especial.

O operador ++ tem alguma magia especial construído em Citando o perlop manpage, sobre o operador ++:.

"undef" é sempre tratada como numérico e, em particular, é alterado para 0 antes de incremento (de modo que uma pós-incremento de um valor undef retornará 0 em vez de "undef").

editar : Para elaborar a diferença, ++ altera o valor no lugar, enquanto + só tem os seus argumentos como entrada. Quando + vê um valor indefinido, tipicamente algo tem de errado se foi, mas para ++, o exemplo da manipulação de hash é muito típico - o usuário quer tratar undef como 0, em vez de ter que verificar e toda vez que inicializar. Assim, parece que faz sentido para tratar estes operadores desta forma.

Outras dicas

Não é que Perl inicializa necessariamente valores, mas que nem sempre alertar sobre eles. Não tente pensar em uma regra para isso, porque você sempre vai encontrar exceções, e apenas quando você acha que tem que descobri, a próxima versão do Perl vai mudar os avisos em você.

Neste caso, como disse Harleqin, os operadores de auto-incremento tem um caso especial.

Alguns operadores deliberadamente omitir o aviso "não inicializado" para sua conveniência porque eles são comumente usados ??em situações em que um "valor 0 ou" padrão para a esquerda ou para a única operando faz sentido.

Estes são: ++ e - (seja pré ou pós), + =, - =, =, | =, ^ =, && =, || =

..

Note que alguns destes erroneamente dar o aviso quando usado em uma variável indexada: veja os testes TODO marcados em http://perl5.git.perl.org/perl.git/blob/HEAD:/t/op/assignwarn.t .

Como Brian mencionado: ele ainda faz isso, ele simplesmente avisa. Avisos informá-lo sobre certas manipulações com efeitos que você pode não ter pretendidos.

Você está especificamente pedindo para o valor de $histogram{$_}, acrescentando 1 a ela e, em seguida, atribuí-la ao mesmo slot. É da mesma forma que eu não esperaria autovivification ao trabalho aqui:

my $hash_ref = $hash_for{$key_level_1};
$hash_ref->{$key_level_2} = $value;

como faz aqui:

$hash_for{$key_level_1}{$key_level_2} = $value;

Mágica, provavelmente, não funciona como otimização. E otimização de compilador iria perceber que a = a + 1 é a mesma coisa que a++ modo que estavam lá um operador de incremento na linguagem de montagem, poderia usar essa instrução otimizada em vez de fingir que era necessário para preservar o primeiro valor e, em seguida, substituí-lo porque ele isn 't realmente necessário.

Optimization é escrutínio extra e sobrecarga uma vez para um melhor desempenho cada corrida. Mas não há nenhuma garantia em uma linguagem dinâmica que você não está adicionando sobrecarga no mesmo ritmo que você de outra forma seria tentar reduzi-la.

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