2008-11-04 16 views
7

Aquí hay algunos Perl simples para contar la cantidad de veces que se produce un valor en una matriz. Esto funciona sin ninguna advertencia.¿Cuándo Perl autoinicializa las variables?

use warnings; 
use strict; 

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

Cuando el cuerpo del bucle se cambia a

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

Perl advierte "Uso del valor no inicializado, además".

¿Qué está pasando debajo del capó? ¿Por qué se inicializa el valor cuando se suministra como un operando al operador ++ y no se inicializa con el operador +?

Respuesta

14

El operador + evalúa tanto el formulario a la izquierda como el formulario a la derecha del mismo, luego devuelve la suma de ambos. La evaluación de llamada hash no ve ningún contexto especial.

El operador ++ ha algo de magia especial construido en Citando de la página de manual perlop, en relación con el operador ++:.

"undef" siempre es tratado como numérico, y en particular se cambia a 0 antes incrementándose (de modo que un incremento posterior de un valor undef devolverá 0 en lugar de "undef").

de edición: Para más detalles sobre la diferencia ++, cambia el valor en el lugar, mientras que + sólo toma sus argumentos como entrada. Cuando + ve un valor indefinido, típicamente algo ha salido mal, pero para ++, su ejemplo de manipulación hash es muy típico: el usuario quiere tratar undef como 0, en lugar de tener que verificar e inicializar cada vez. Entonces parece que tiene sentido tratar a estos operadores de esta manera.

7

No es que Perl inicialice necesariamente los valores, pero eso no siempre los advierte. No intente pensar en una regla para esto porque siempre encontrará excepciones, y justo cuando crea que lo tiene resuelto, la próxima versión de Perl cambiará las advertencias sobre usted.

En este caso, como dijo Harleqin, los operadores de autoincremento tienen un caso especial.

0

Como dijo Brian: todavía lo hace, solo te lo advierte. Las advertencias le informan sobre ciertas manipulaciones con efectos que podría no haber previsto.

Específicamente preguntando por el valor de $histogram{$_}, agregando 1 a él y luego asignándolo a la misma ranura. Es de la misma manera que yo no esperaría autovivification para trabajar aquí:

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

como lo hace aquí:

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

magia probablemente no funciona de optimización. Y la optimización del compilador notaría que a = a + 1 es lo mismo que a++, de modo que si hubiera un operador de incremento en el lenguaje ensamblador, podría usar esa instrucción optimizada en lugar de pretender que necesitaba preservar el primer valor, y luego sobrescribirlo porque no está en realidad es necesario.

La optimización es un escrutinio adicional y una sola vez para un mejor rendimiento en cada ejecución. Pero no hay garantía en un lenguaje dinámico de que no esté agregando sobrecarga a la misma velocidad que de otra manera estaría tratando de reducirla.

+0

Si bien las advertencias no rompen directamente la compilación, deben tenerse en cuenta sin embargo. – Svante

7

Ciertos operadores omiten deliberadamente la advertencia "no inicializada" , ya que se utilizan comúnmente en situaciones en las que un 0 o "" valor predeterminado para el operando izquierdo o solo tiene sentido.

Estos son: ++ y - (pre o post), + =, - =,. =, | =,^=, & & =, || =.

Tenga en cuenta que algunos de estos dan erróneamente la advertencia cuando se usan en una variable vinculada: vea las pruebas marcadas TODO en http://perl5.git.perl.org/perl.git/blob/HEAD:/t/op/assignwarn.t.

Cuestiones relacionadas