Когда можно использовать неопределенную переменную в perl с включенными предупреждениями? - PullRequest
15 голосов
/ 30 января 2010

При включенных предупреждениях perl обычно печатает Use of uninitialized value $foo, если в выражении используется $foo и ему не присвоено значение, но в некоторых случаях все в порядке, а переменная обрабатывается как false , 0 или '' без предупреждения.

В каких случаях можно использовать неинициализированную / неопределенную переменную без предупреждения?

Ответы [ 4 ]

18 голосов
/ 30 января 2010

Резюме

  • Булевы тесты
  • Увеличение или уменьшение неопределенного значения
  • Добавление к неопределенному значению
  • Autovivification
  • Другие мутаторы

Булевы тесты

Согласно документации perlsyn ,

Число 0, строки '0' и '', пустой список () и undef все ложно в логическом контексте. Все остальные значения верны.

Поскольку неопределенное значение равно false, следующая программа

#! /usr/bin/perl

use warnings;

my $var;
print "A\n" if $var;
$var && print "B\n";
$var and print "C\n";
print "D\n" if !$var;
print "E\n" if not $var;
$var or print "F\n";
$var || print "G\n";

выводит D - G без предупреждений.

Увеличение или уменьшение неопределенного значения

Нет необходимости явно инициализировать скаляр в ноль, если ваш код будет увеличивать или уменьшать его хотя бы один раз:

#! /usr/bin/perl

use warnings;

my $i;
++$i while "aaba" =~ /a/g;
print $i, "\n";

Код выше выводит 3 без предупреждений.

Добавление к неопределенному значению

Подобно неявному нулю, нет необходимости явно инициализировать скаляры для пустой строки, если вы добавите к ней хотя бы один раз:

#! /usr/bin/perl

use warnings;
use strict;

my $str;
for (<*>) {
  $str .= substr $_, 0, 1;
}
print $str, "\n";

Autovivification

Одним из примеров является "автовивификация". Из статьи Википедии :

Автовивификация - отличительная черта языка программирования Perl, включающая динамическое создание структур данных. Autovivification - это автоматическое создание ссылки на переменную при разыменовании неопределенного значения. Другими словами, автовивификация Perl позволяет программисту ссылаться на структурированную переменную и произвольные подэлементы этой структурированной переменной без предварительного явного объявления о существовании переменной и ее полной структуре.

Например:

#! /usr/bin/perl

use warnings;

my %foo;
++$foo{bar}{baz}{quux};

use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%foo;

Несмотря на то, что мы не инициализируем промежуточные ключи явно, Perl позаботится о строительных лесах:

$VAR1 = {
  'bar' => {
    'baz' => {
      'quux' => '1'
    }
  }
};

Без автовивификации код потребует больше шаблонов:

my %foo;
$foo{bar} = {};
$foo{bar}{baz} = {};
++$foo{bar}{baz}{quux};  # finally!

Не путайте автовивификацию с неопределенными значениями, которые она может выдавать. Например, с

#! /usr/bin/perl

use warnings;

my %foo;
print $foo{bar}{baz}{quux}, "\n";
use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%foo;

получаем

Use of uninitialized value in print at ./prog.pl line 6.

$VAR1 = {
  'bar' => {
    'baz' => {}
  }
};

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

Другие примеры автовивификации:

  • ссылка на массив

    my $a;
    push @$a => "foo";
    
  • ссылка на скаляр

    my $s;
    ++$$s;
    
  • ссылка на хеш

    my $h;
    $h->{foo} = "bar";
    

К сожалению, Perl (пока!) Не автовифицирует следующее:

my $code;
$code->("Do what I need please!");

Другие мутаторы

В ответе на аналогичный вопрос , ysth сообщает

Некоторые операторы специально для вашего удобства намеренно пропускают «неинициализированное» предупреждение, поскольку они обычно используются в ситуациях, когда имеет значение 0 или «» значение по умолчанию для левого или единственного операнда.

Это: ++ и -- (до или после), +=, -=, .=, |=, ^=, &&=, ||=.

Будучи «определенным или», //= счастливо изменяет неопределенное значение без предупреждения.

2 голосов
/ 31 января 2010

Всегда исправить предупреждения даже досадные раздражающие.

Неопределенные предупреждения могут быть отключены. Вы можете сделать это, создав новую область действия для операции. См. perldoc perllexwarn для получения дополнительной информации. Этот метод работает во всех версиях Perl.

{
  no warnings 'uninitialized';
  my $foo = "foo" + undef = "bar";
}

Для многих бинарных операторов вы можете использовать новые вещи Perl 5.10, ~~ и //; См. perldoc perlop для получения дополнительной информации.

use warnings;
my $foo = undef;
my $bar = $foo // ''; ## same as $bar = defined $foo ? $foo : ''

также является вариантом //=, который устанавливает переменную, если она не определена:

$foo //= '';

Оператор Smart Matching (~~) - это круто, он позволяет проводить умные сравнения, это довольно изящно, проверьте это в perldoc perlsyn:

use warnings;
my $foo = "string";
say $foo eq undef;  # triggers warnings
say $foo ~~ undef;  # no undef warnings
2 голосов
/ 30 января 2010

Пока что я нашел следующие случаи:

  • автовивификация ( ответ гбакона )
  • логический контекст, например if $foo или $foo || $bar
  • с ++ или --
  • левая сторона +=, -= или .=

Есть ли другие?

0 голосов
/ 31 января 2010

Реальный ответ должен быть таким: почему вы хотите включить это предупреждение? undef является очень хорошим значением для переменной (как может сказать любой, кто когда-либо работал с базой данных), и часто имеет смысл различать true (что-то произошло), false (ничего не произошло) и undef (произошла ошибка).

Вместо того, чтобы сказать

use strict;
use warnings;

говорят

use common::sense;

и вы получите все преимущества предупреждений, но с отключенными раздражающими, такими как неопределенные переменные.

здравый смысл доступен в CPAN.

...