Gibt es in Perl anmutige Möglichkeiten, undfische Umkehrung in 0 manuell auf 0 zu konvertieren?

StackOverflow https://stackoverflow.com/questions/1351103

  •  20-09-2019
  •  | 
  •  

Frage

Ich habe ein Fragment in dieser Form:

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;

Die Realität ist noch chaotischer, da mehr als zwei Variablen betroffen sind.

Was ich wirklich schreiben möchte, ist Folgendes:

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

und habe undse, dass ich auf 0 korrekt bewertet habe, aber ich bekomme diese Warnungen in fast jedem Lauf:

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

Was ist der beste Weg, um diese Nachrichten verschwinden zu lassen?

NB: Ich verwende strenge und verwende Warnungen, wenn das relevant ist.

War es hilfreich?

Lösung

Es ist gut, dass Sie verwenden strict und warnings. Der Zweck der Warnungen ist es, Sie zu alarmieren, wenn Perl Verhalten sieht, das wahrscheinlich unbeabsichtigt (und damit falsch) ist. Wenn Sie es absichtlich tun, ist es vollkommen in Ordnung, die Warnung lokal zu deaktivieren. undef wird als behandelt 0 in numerischen Kontexten. Wenn Sie mit beiden und definierten Werten einverstanden sind und sie auf Null bewerten lassen, deaktivieren Sie einfach die Warnung:

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

HINWEIS: Deaktivieren Sie nur die Warnungen, die Sie benötigen, und tun Sie dies im kleinsten Bereich.

Wenn Sie die Deaktivierung von Warnungen abgeneigt haben, gibt es andere Optionen. Ab Perl 5.10 können Sie die verwenden // (definierter) Operator zum Festlegen von Standardwerten. Zuvor benutzen die Leute oft die || (logisch-or), aber das kann das Falsche für Werte tun, die auf False bewertet werden. Der robuste Weg zur Standardwerte in den Versionen von Perl vor 5.10 besteht darin, zu überprüfen, ob es sich um sie handelt defined.

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

Andere Tipps

Sie können die "nicht initialisierte" Warnung für eine Sekunde ausschalten:

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

Oder Sie können kurzfristig auf Null vergeben werden:

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

Sieht für mich aber nicht sehr gut aus.

Wenn Sie sie hinzufügen, filtern Sie einfach die undefs heraus.

use List::Util 'sum';

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

Oder auch

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 diesem Fall ist es in Ordnung, falsche Werte aufgrund Ihres Fallback -Werts zu behandeln.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top