비 초기 해시 키가 Perl에서 기본값이 0인가요?
-
03-07-2019 - |
문제
다음과 유사한 Perl 코드가 있습니다.
# -- start --
my $res;
# run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{
if( $row->[4] =~ /PA/ ) {
$res->{ipv6}{pa}{$row->[2]}++;
} elsif( $row->[4] eq 'PI' ) {
$res->{ipv6}{pi}{$row->[2]}++;
}
}
# -- stop --
어떤 시점에도 $res
쿼리 결과를 반복하기 전에 설정했지만 코드는 잘 실행됩니다.
각 값 전에 인쇄 명세서를 넣을 때 두 경우 모두 공백이 발생하지만 증분 증분이 적용된 후 인쇄 문이 오면 조직의 IPv6 리소스 수에 따라> = 1의 값을 얻습니다.
내 질문은 Perl의 비 초기 해시 키를 자동으로 0 인 것을 의미하는 것입니다.
초보자 질문으로 만나면 죄송하지만 그런 구조에 익숙하지 않습니다. $hashref->{foo}->{bar}++
값이 아직 명시 적으로 할당되지 않은 경우 $hashref->{foo}->{bar}
. 미리 감사드립니다!
해결책
값은 자동으로 0이 아닙니다. 값은 처음에는 정의되지 않았습니다. 그러나 숫자처럼 취급하면 (예 : 적용 ++
그것에), 그 다음 Perl은 그것을 0처럼 취급합니다. 끈처럼 취급하면 (예 : 적용 .
그 다음), Perl은 그것을 빈 줄처럼 취급합니다.
에서 perldoc perlsyn
, '선언'아래 :
Perl에서 선언해야 할 유일한 것은 보고서 형식과 서브 루틴 (때로는 서브 루틴조차도)입니다. 변수는 정의되지 않은 값 ( "undef")이 정의 된 값이 할당 될 때까지 "undef"가 아닌 다른 값을 보유합니다. 숫자로 사용될 때 "undef"는 0으로 취급됩니다. 문자열로 사용하면 빈 문자열로 취급됩니다. ""; 그리고 할당되지 않은 참조로 사용되면 오류로 취급됩니다.
다른 팁
Telemachus의 게시물에 대해 자세히 설명하기 위해, 비 초기 값은 정의되지 않습니다. 구조의 깊은 부분은 다음과 같습니다 자가 변형. 이것은 데이터 구조가 자동으로 만들어지는 편리한 기능입니다. 자가 변형은 원할 때 훌륭하지만 방지하고 싶을 때는 고통이 될 수 있습니다. 자동 변형 이해에 대한 인터넷 주변에는 많은 튜토리얼, 기사 및 게시물이 있습니다.
정의되지 않은 채로 $ref
그리고 $ref->{ipv6}{pa}{'foo'}++
, $ref
값이 할당됩니다.
$ref = {
ipv6 => {
pa => {
foo => undef
}
}
};
undef가 0으로 numife으므로 0 ++를 얻습니다. 1의 최종 결과는 다음과 같습니다. ref->{ipv6}{pa}{'foo'} == 1
.
경고가 활성화 된 경우 (그렇습니다 use warnings;
, 당신은 그렇지 않습니까?)이 정의되지 않은 값에서 작동 할 때 "비 초기의 값"경고를 받게됩니다. 단위화 된 값을 증가시키는 것이 원하는 동작이라면, 원하는 경고 그룹을 코드의 제한된 부분에서 전환 할 수 있습니다.
use strict;
use warnings;
my $res;
// run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{ no warnings 'uninitialized';
if( $row->[4] =~ /PA/ ) {
$res->{ipv6}{pa}{$row->[2]}++;
} elsif( $row->[4] eq 'PI' ) {
$res->{ipv6}{pi}{$row->[2]}++;
}
}
경고 계층 구조를 찾을 수 있습니다 perllexwarn.
기본적으로 정의되지 않지만 증가 할 때 0 인 것처럼 취급됩니다.
Perl Parlance의 용어는 'AutoVivified'입니다.
아마도 당신이하고 싶은 것은 사용하는 것입니다 키워드가 있습니다:
$res->{ipv6}{pa}{$row->[2]}++ if exists($res->{ipv6}{pa}{$row->[2]});
초기화되지 않은 해시와 같은 것은 없습니다 열쇠. 비 초기화 될 수있는 것은 다음과 같습니다 값 특정 키를 위해. 해시 값은 단지 스칼라 값입니다. 변수와 같은 것은 아닙니다 $foo
.
예제에는 상호 작용하는 몇 가지 다른 Perl 기능이 있습니다.
처음에 $res
정의되지 않았습니다 (즉, 가치가 있습니다 undef
). 비 초기 값을 해시 참조로 사용하는 경우 ( $res->{ipv6}...
) perl "autovivivivivivies"로서. 즉, Perl은 익명 해시를 생성하고 값을 대체합니다. undef
새로운 해시를 참조하여. 이 프로세스는 결과 값을 참조로 사용할 때마다 (조용히) 반복됩니다.
결국, 당신은 당신의 길을 자동으로 바꿉니다 $res->{ipv6}{pa}{$row->[2]}
, 정의되지 않았습니다. 이것은 단지 스칼라 값이라는 것을 기억하십시오 $foo
. 행동은 말과 동일합니다
my $foo;
$foo++;
Perl은 정의되지 않은 값을 사용할 때 특별한 일을합니다. 숫자로 사용하면 Perl이 0으로 변환합니다. 문자열로 사용하면 Perl이`(빈 문자열)으로 변환합니다. 대부분의 상황에서는 "비 초기 가치 사용 ..."경고가 활성화 된 경우 경고를 얻을 수 있습니다 (필요한 경우). 그만큼 자동 증가 운영자 (++
그러나)는 특별한 경우입니다. 편의를 위해 값을 조용히 변환합니다 undef
에게 0
그것을 증가시키기 전에.