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

.
Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top