En Perl, ¿hay forma elegante para convertir undef a 0 manualmente?
Pregunta
Tengo un fragmento en esta forma:
my $a = $some_href->{$code}{'A'}; # a number or undef
my $b = $some_href->{$code}{'B'}; # a number or undef
$a = 0 unless defined($a);
$b = 0 unless defined($b);
my $total = $a + $b;
La realidad es aún más complicado, ya que más de dos variables se refiere.
Lo que realmente quiero escribir es la siguiente:
my $total = $some_href->{$code}{'A'} + $some_href->{$code}{'B'};
y tengo undef evalúa correctamente a 0 pero consigo estas advertencias en casi cada carrera:
Use of uninitialized value in addition (+) at Stats.pm line 192.
¿Cuál es la mejor manera de hacer que estos mensajes desaparecen?
Nota: I '' 'usar estrictas advertencias de uso' y si es relevante que s
.Solución
Es bueno que usted está utilizando strict
y warnings
. El propósito de las advertencias es para avisarle cuando Perl ve un comportamiento que es probable que sea intencional (y por lo tanto incorrecto). Cuando estás haciendo deliberadamente, que está perfectamente bien para desactivar la alerta a nivel local. undef
se trata como 0
en contextos numéricos. Si estás bien con ambos con valores no definidos y que ellos evalúan a cero, simplemente desactivar la advertencia:
my $total;
{
no warnings 'uninitialized';
$total = $some_href->{$code}{A} + $some_href->{$code}{B};
}
Nota:. Desactivar sólo las advertencias que necesita, y lo hacen en el ámbito más pequeño posible
Si usted es reacio a deshabilitar las advertencias, hay otras opciones. A partir de Perl 5.10 se puede utilizar el operador de //
(definido o) para establecer los valores por defecto. Antes de que las personas a menudo usan el ||
(lógico-o), pero que puede hacer lo incorrecto de los valores que se evalúan como falso. La forma más robusta a los valores predeterminados en la pre-5.10 versiones de Perl es comprobar si están defined
.
$x = $y // 42; # 5.10+
$x = $y || 42; # < 5.10 (fragile)
$x = defined $y ? $y : 42; # < 5.10 (robust)
Otros consejos
Puede desactivar la advertencia “no inicializado” por un segundo:
my $a;
my $b = 1;
{
no warnings 'uninitialized';
my $c = $a+$b; # no warning
}
my $c = $a+$b; # warning
O bien, puede causar un cortocircuito a cero:
my $d = ($a||0)+$b; # no warning
No se ve muy agradable para mí, sin embargo.
Como se va a añadir ellos sólo tiene que filtrar los undefs.
use List::Util 'sum';
my $total = sum (0, grep {defined} $some_href->{$code}{'A'}, $some_href->{$code}{'B'});
O incluso
use List::Util 'sum';
my $total = sum (0, grep {defined} map {$some_href->{$code}{$_}} 'A', 'B');
my $a = $some_href->{$code}{'A'} || 0;
my $b = $some_href->{$code}{'B'} || 0;
my $total = $a + $b;
En este caso, está bien para tratar los falsos valores los mismos que los valores no definidos, debido a su valor de retorno.