Domanda

Ho un frammento in questa 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 realtà è ancora più disordinato, da più di due variabili sono interessati.

Quello che voglio scrivere è questo:

my $total = $some_href->{$code}{'A'} + $some_href->{$code}{'B'};

e ho undef valutare correttamente a 0 ma ottengo questi avvertimenti in quasi ogni corsa:

Use of uninitialized value in addition (+) at Stats.pm line 192.

Qual è il modo migliore per rendere questi messaggi vanno via?

NB: I 'usare severe' e 'Usa avvertimenti' Se questo è rilevante

.
È stato utile?

Soluzione

E 'bene che si sta utilizzando e strict warnings. Lo scopo di avvertimenti è quello di avvisare l'utente quando Perl vede un comportamento che è probabile che sia non intenzionale (e quindi non corretta). Quando si sta facendo volutamente, è perfettamente bene per disattivare l'avviso a livello locale. undef viene trattato come 0 in contesti numerici. Se stai bene con entrambi che hanno valori non definiti e di farle valutare a zero, basta disattivare l'avviso:

my $total;
{
  no warnings 'uninitialized';
  $total = $some_href->{$code}{A} + $some_href->{$code}{B};
}

. Nota: Disattivare solo gli avvertimenti che è necessario, e di farlo nel più piccolo ambito possibile

Se siete contrari alla disattivazione di avvertimenti, ci sono altre opzioni. A partire dal Perl 5.10 è possibile utilizzare il // (definita o) all'operatore di impostare i valori predefiniti. Prima che le persone usano spesso la || (logico-o), ma che può fare la cosa sbagliata per i valori che restituiscono falso. Il modo robusto ai valori di default in pre-5.10 versioni di Perl è quello di verificare se sono defined.

$x = $y // 42;             # 5.10+
$x = $y || 42;             # < 5.10 (fragile)
$x = defined $y ? $y : 42; # < 5.10 (robust)

Altri suggerimenti

È possibile disattivare l'avviso “non inizializzato” per un secondo:

my $a;
my $b = 1;
{
    no warnings 'uninitialized';
    my $c = $a+$b; # no warning
}
my $c = $a+$b; # warning

In alternativa, è possibile corto circuito a zero:

my $d = ($a||0)+$b; # no warning

Non sembra molto bello per me però.

Come li sta aggiungendo, basta filtrare i undefs.

use List::Util 'sum';

my $total = sum (0, grep {defined} $some_href->{$code}{'A'}, $some_href->{$code}{'B'});

O anche

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;

In questo caso, va bene per il trattamento di falsi valori lo stesso di valori non definiti a causa del vostro valore di sicurezza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top