В Perl есть ли изящный способ преобразовать Undef в 0 вручную?

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

  •  20-09-2019
  •  | 
  •  

Вопрос

У меня есть фрагмент в этой форме:

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;

Реальность еще более грязная, поскольку касается более двух переменных.

Я действительно хочу написать:

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

и правильно оценить до 0, но я получаю эти предупреждения почти во всех пробегах:

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

Как лучше всего заставить эти сообщения уйти?

NB: Я «использую строгие» и «используйте предупреждения», если это актуально.

Это было полезно?

Решение

Хорошо, что вы используете strict а также warnings. Анкет Целью предупреждений является предупреждение вас, когда Perl видит поведение, которое, вероятно, будет непреднамеренным (и, следовательно, неверным). Когда вы делаете это намеренно, это прекрасно отключить предупреждение на месте. undef рассматривается как 0 в числовых контекстах. Если у вас все в порядке с тем, что у вас есть неопределенные ценности и оценивать их до нуля, просто отключите предупреждение:

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

Примечание. Отключите только предупреждения, которые вам нужно, и сделайте это в максимально возможной области.

Если вы не склонны к отключению предупреждений, есть и другие варианты. По состоянию на Perl 5.10 вы можете использовать // (Определен или) оператор для установки значений по умолчанию. До этого люди часто используют || (логично-или), но это может сделать неправильную вещь для значений, которые оцениваются до ложности. Надежный способ к значениям по умолчанию в версиях Perl до 5,10-это проверить, если они defined.

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

Другие советы

Вы можете отключить «ненициализированное» предупреждение на секунду:

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

Или вы можете короткометраться до нуля:

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

Хотя мне не очень приятно.

Когда вы добавляете их, просто отфильтруйте Undefs.

use List::Util 'sum';

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

Или даже

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;

В этом случае можно обрабатывать ложные значения так же, как и неопределенные значения из -за вашего задержки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top