En Perl, est-il de convertir manière gracieuse FNUD à 0 manuellement?
Question
J'ai un fragment sous cette forme:
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 réalité est encore plus désordonnée, depuis plus de deux variables sont concernés.
Ce que je veux vraiment écrire est ceci:
my $total = $some_href->{$code}{'A'} + $some_href->{$code}{'B'};
et correctement à FNUD sont évalués à 0 mais je reçois ces avertissements dans presque chaque course:
Use of uninitialized value in addition (+) at Stats.pm line 192.
Quelle est la meilleure façon de faire ces messages disparaissent?
NB: j'utiliser strictes »et « utiliser des avertissements » Si c'est pertinent
.La solution
Il est bon que vous utilisez strict
et warnings
. Le but des avertissements est de vous alerter lorsque le comportement voit Perl qui est susceptible d'être accidentelle (et donc incorrect). Lorsque vous faites délibérément, il est parfaitement bien pour désactiver l'avertissement localement. undef
est traité comme 0
dans des contextes numériques. Si vous êtes d'accord avec les deux ayant des valeurs non définies et les ayant évaluer à zéro, il suffit de désactiver l'avertissement:
my $total;
{
no warnings 'uninitialized';
$total = $some_href->{$code}{A} + $some_href->{$code}{B};
}
Remarque:. Désactiver uniquement les avertissements dont vous avez besoin, et le faire dans le cadre le plus petit possible
Si vous êtes opposé à désactiver les avertissements, il y a d'autres options. A partir de Perl 5.10, vous pouvez utiliser l'opérateur //
(ou défini) pour définir des valeurs par défaut. Avant que les gens utilisent souvent le ||
(ou logique), mais qui peut faire la mauvaise chose pour les valeurs évaluées à false. La façon robuste aux valeurs par défaut dans les versions antérieures à 5.10 de Perl est de vérifier si elles sont defined
.
$x = $y // 42; # 5.10+
$x = $y || 42; # < 5.10 (fragile)
$x = defined $y ? $y : 42; # < 5.10 (robust)
Autres conseils
Vous pouvez désactiver pour un second avertissement « non initialisée »:
my $a;
my $b = 1;
{
no warnings 'uninitialized';
my $c = $a+$b; # no warning
}
my $c = $a+$b; # warning
Ou vous pouvez court-circuit à zéro:
my $d = ($a||0)+$b; # no warning
ne semble pas très gentil avec moi bien.
Comme vous les ajoutez, filtrez simplement les undefs.
use List::Util 'sum';
my $total = sum (0, grep {defined} $some_href->{$code}{'A'}, $some_href->{$code}{'B'});
Ou même
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;
Dans ce cas, il est OK pour traiter les fausses valeurs les mêmes que les valeurs non définies en raison de votre valeur de repli.