Неинициализированный хеш-ключ имеет значение по умолчанию ноль в Perl?

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

  •  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 никогда не устанавливается до итерации по результатам запроса, но код работает просто отлично.

Когда я помещаю операторы печати перед каждым значением, в обоих случаях я получаю пробелы, но если операторы печати появляются после применения приращения, я получаю значение > = 1 в зависимости от того, сколько ресурсов IPv6 имеет организация.

Мой вопрос: следует ли мне считать, что неинициализированный хеш-ключ в Perl автоматически имеет значение ноль?

Извините, если это выглядит как вопрос новичка, но я просто не знаком с такой конструкцией то есть $ hashref- > {foo} - > {bar} ++ где значение еще не было явно назначено для $ hashref- > {foo} - > {bar} . Заранее спасибо!

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

Решение

Значение не равно нулю автоматически. Значение не определено изначально. Однако, если вы рассматриваете его как число (например, применяете к нему ++ ), то Perl обрабатывает его как ноль. Если вы рассматриваете его как строку (например, применяете к нему . ), то Perl обрабатывает его как пустую строку.

Из perldoc perlsyn в разделе «Объявления»:

  

Единственное, что вам нужно объявить в   Perl - это форматы отчетов и   подпрограммы (а иногда даже не   Подпрограммы). Переменная содержит   неопределенное значение (" undef "), пока оно не   было назначено определенное значение, которое   является чем-то иным, чем "undef". когда   используется в качестве числа "undef" лечится   как 0; когда используется как строка, это   рассматривается как пустая строка, " " ;; а также   при использовании в качестве эталона, который не является & # 8217; т   будучи назначенным, он рассматривается как   ошибка.

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

Чтобы уточнить пост Телемаха, неинициализированные значения будут неопределенными. Глубокие части структуры автоматически оживлены . Это удобная функция, где структуры данных создаются для вас автоматически. Автовификация хороша, когда вы этого хотите, но это может быть болезненно, если вы хотите предотвратить это. В сети много учебников, статей и постов по пониманию автовивификации.

Так, учитывая неопределенные $ ref и $ ref- > {ipv6} {pa} {'foo'} ++ , $ ref будет присвоено значение:

$ref = { 
     ipv6 => { 
          pa => { 
              foo => undef
          }
     }
};

Тогда undef будет увеличен, поскольку undef нумерует до 0, мы получаем 0 ++, который равен 1. Окончательный результат: ref- > {ipv6} {pa} {'foo'} == 1 .

Если у вас включены предупреждения (вы используете предупреждения; , не так ли?), вы получите " неинициализированное значение " предупреждение при работе с этими неопределенными значениями. Если требуется увеличить значение унитарной величины, то вы можете отключить нужную группу предупреждений для ограниченной части вашего кода:

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 .

Он в основном не определен, но обрабатывается так, как будто он равен нулю при увеличении.

Термин на языке Perl - «автовифицированный».

Вероятно, вы захотите использовать существует ключевое слово :

$res->{ipv6}{pa}{$row->[2]}++ if exists($res->{ipv6}{pa}{$row->[2]});

Нет такой вещи как неинициализированный хеш-ключ . То, что может быть неинициализировано, это значение для определенного ключа. Значение хеша это просто скалярное значение; это ничем не отличается от такой переменной, как $ foo .

В вашем примере взаимодействует пара различных функций Perl.

Изначально $ res не определено (т. е. имеет значение undef ). Когда вы используете неинициализированное значение в качестве ссылки на хеш (как в $ res- > {ipv6} ... ), Perl " autovivizes " это как один. То есть Perl создает анонимный хеш и заменяет значение undef ссылкой на новый хеш. Этот процесс повторяется (тихо) каждый раз, когда вы используете результирующее значение в качестве ссылки.

В конце концов, вы автоматически выбираете путь к $ res- > {ipv6} {pa} {$ row- > [2]} , который не определен. Помните, что это просто скалярное значение, например $ foo . Поведение такое же, как сказать

my $foo;
$foo++;

Perl делает особые вещи, когда вы используете неопределенные значения. Если вы используете их как число, Perl преобразует их в 0. Если вы используете их как строку, Perl преобразует их в '' (пустая строка). В большинстве случаев вы получите " Использование неинициализированного значения ... " предупреждение, если у вас включены предупреждения (что вы должны). оператор автоматического увеличения ( + + ) это особый случай. Для удобства он тихо преобразует значение из undef в 0 перед его увеличением.

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