Использование
each()
в хэше после вставки без сброса итератора хеширования приводит к неопределенному поведению, интерпретатор Perl:0x13932010
в/srv/data203806/MUXmh-Migration/Newperl/localperl/lib/site_perl/5.18.1/x86_64-linux-thread-multi/forks.pm
строке 1736.
Все в моем коде работает нормально, но я получаю эту ошибку. Как я могу подавить это предупреждение?
3 ответа
Это предупреждает:
use strict;
use warnings;
use Data::Dumper;
my %h = (a=>1);
while (my ($k,$v) = each %h) {
$h{b} = 2;
}
print Dumper \%h;
Это заглушает предупреждение:
use strict;
use warnings;
use Data::Dumper;
my %h = (a=>1);
{
no warnings qw(internal);
while (my ($k,$v) = each %h) {
$h{b} = 2;
}
}
print Dumper \%h;
Обратите внимание, что категория предупреждений для отключения звука называется internal
. Откуда я это узнал? Есть ли у меня какая-то потрясающая память для категорий предупреждений Perl? Нет. Все сообщения об ошибках и предупреждениях Perl хорошо документированы в perldiag; для каждого предупреждения указывается категория, к которой оно принадлежит.
Тем не менее, это предупреждение говорит вам о реальной проблеме. Поведение вашего кода не определено; если вы переключитесь на другую версию Perl, он может внезапно начать работать по-другому. Лучше, чем отключать предупреждение, исправить ваш код!
В моем примере выше быстрым решением было бы использовать each
для циклического перебора копии %h
, а не самого %h
.
use strict;
use warnings;
use Data::Dumper;
my %h = (a=>1);
{
my %tmp = %h;
while (my ($k,$v) = each %tmp) {
$h{b} = 2;
}
}
print Dumper \%h;
Настоящий вопрос здесь: что происходит? В документации указано, что это не определено. Как программист Perl я могу с этим жить. Мне лично все равно, какой набор каждый () вернет, если не застрять в одном месте. Есть несколько возможностей, но прежде чем я уточню, я должен сказать, что я использую each () - плохой итератор, поскольку встроенный лучше, чем each (), не предоставляется.
Итак, последовательность такова: - Некоторая случайная пара возвращается из набора ключ / значение, а затем перемещается в ожидаемой форме. (меня это устраивает, я не добавляю кучу всякой всячины) - Сброс для запуска. очевидно, что этого не происходит, иначе в документации сказано. (Я не поддерживаю это действие) - each () возвращает набор (undef, undef) и после этого работает должным образом. Не мой первый выбор, но хорошо, если это одна из неопределенных возможностей. - теряет рассудок; Я бы использовал здесь красочную метафору, но в основном теряю всякий контроль, и Perl ломается сам. Насколько я могу судить, этого не происходит.
Как предложили другие участники, лучше всего кодировать так, чтобы предупреждение не создавалось; однако я привел один пример (простой итератор), где я нажимаю на каждую с высокой частотой (выше), а вставляю и удаляю элементы с меньшей частотой. Я считаю, что поведение Perl без предупреждения вполне подходит.
В некоторых случаях, когда мне требовалось лучшее управление итератором, я создавал подходящий класс для реализации поведения, которое я считал нужным.
Следующая техника, которая минимально изменяет существующий код, подавляет предупреждение, избегая опасной операции:
foreach my $key (keys %hash) {
my $value = $hash{$key};
# ...
}
Назначение $ value гарантирует, что вам не нужно переделывать код, который следует в содержащем блоке.
Похожие вопросы
Новые вопросы
perl
Perl - это процедурный высокоуровневый динамический язык программирования общего назначения, известный своей собственной поддержкой регулярных выражений и возможностей синтаксического анализа строк. Пожалуйста, используйте этот тег для вопросов о Perl в целом. Для вещей, связанных с новым (но связанным) языком Raku (ранее «Perl 6»), используйте тег raku. Для регулярных выражений в стиле Perl на других языках используйте тег regex или, если они основаны на библиотеке PCRE, тег pcre.