Perl에서는 undef를 수동으로 변환하는 우아한 방법이 있습니까?
문제
이 형식의 조각이 있습니다.
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'};
그리고 Undef가 0으로 올바르게 평가되었지만 거의 모든 실행에서 이러한 경고를받습니다.
Use of uninitialized value in addition (+) at Stats.pm line 192.
이 메시지를 사라지게하는 가장 좋은 방법은 무엇입니까?
NB : 관련이있는 경우 '엄격한'및 '경고 사용'을 사용합니다.
해결책
당신이 사용하는 것이 좋습니다 strict
그리고 warnings
. 경고의 목적은 Perl이 의도하지 않을 가능성이있는 행동을 볼 때 경고하는 것입니다. 의도적으로 할 때 경고를 로컬에서 비활성화하는 것은 완벽하게 괜찮습니다. undef
처리됩니다 0
숫자 맥락에서. 정의되지 않은 값이없고 0으로 평가하는 것이 괜찮다면 경고를 비활성화하십시오.
my $total;
{
no warnings 'uninitialized';
$total = $some_href->{$code}{A} + $some_href->{$code}{B};
}
참고 : 필요한 경고 만 비활성화하고 가능한 가장 작은 범위에서 그렇게하십시오.
경고를 비활성화하는 데 반대하는 경우 다른 옵션이 있습니다. Perl 5.10 기준으로 사용할 수 있습니다 //
(정의 또는) 연산자는 기본값을 설정합니다. 그 전에는 사람들이 종종 사용합니다 ||
(논리적 또는) 그러나 그것은 거짓으로 평가하는 값에 대해 잘못된 일을 할 수 있습니다. Pre-5.10 버전의 기본값을 기본값으로하는 강력한 방법은 PERL이 있는지 확인하는 것입니다. 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
또는 단락을 0으로 단락시킬 수 있습니다.
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;
이 경우 폴백 값으로 인해 잘못된 값을 정의되지 않은 값과 동일하게 처리해도 괜찮습니다.