С включенными предупреждениями жемчуг обычно печатает Use of uninitialized value $foo
если $foo
используется в выражении и не был присвоен значение, но в некоторых случаях оно в порядке, и переменную рассматривают как ложь, 0
, или ''
без предупреждения.
Каковы случаи, где неинициализированная / неопределенная переменная может использоваться без предупреждения?
Согласно документации perlsyn ,
Число
0
, строки'0'
и''
, пустой список()
иundef
- все они ложны в логическом контексте. Все остальные значения верны.
Поскольку неопределенное значение ложно, следующая программа
#! /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";
Один пример: " автовивификация."Из статьи в Википедии :
Автовивификация - отличительная особенность языка программирования Perl, включающая динамическое создание структур данных. Автовивификация - это автоматическое создание ссылки на переменную при разыменовании неопределенного значения. Другими словами, автовивификация 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 или «» по умолчанию для левого или единственного операнда имеет смысл.
Это:
++
и-
(до или после),+ =
,- =
,.=
,| =
,^ =
,&& =
,|| =
.
Будучи «определенным-или», // =
успешно изменяет неопределенное значение без предупреждения.
Если вы ищете примеры о том, как разработать приложение, посмотрите на многие рамки - это хороший запуск. Даже только их структура файлов даст вам идею. Как правило, они организуют свой код в модули, где также проживают как HTML-шаблоны HTML. Ни один, в частности, лучше посмотреть, но попробуйте: CakePhp, Symfony, Codeigniter или Agavi.
Они не будут делать отличную работу по предложению того, как организовать файлы JavaScript и CSS. Когда я делаю приложение, у меня обычно есть только горсть файлов CSS. Я удивлен, что вам, кажется, нужно понадобиться на странице, но если вы сделаете: встраивать их. Преимущество листов внешних стилей полностью потеряно, если нет ничего многоразового использования о своем стиле. Файлы JavaScript, опять же, если они не используются, вы должны просто встраивать их. Менее HTTP-запросы на нагрузку на страницу делает всех счастливыми.
Когда вы оказываете себя чистящим для определенного файла, который упрямо не поставит себя, GREP
- это бесценный инструмент. Вот случайная статья , которая иллюстрирует свое использование.
всегда Удачные предупреждения Даже Pesky Anoying.
Неопределенные предупреждения могут быть выключены. Вы можете сделать это, создавая новый объем для операции. См. 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 //= '';
Умный сопоставление ( ~~
) Оператор довольно крутая, и позволяет смарт Сравнения, это вид нефте, проверьте это в Perldoc perlsyn
:
use warnings;
my $foo = "string";
say $foo eq undef; # triggers warnings
say $foo ~~ undef; # no undef warnings
Реальный ответ должен быть: почему вы хотите включить это предупреждение? undef - это совершенно хорошее соотношение для переменной (как любой, кто когда-либо работал с базой данных, может сказать вам), и это часто имеет смысл дифференцироваться между True (что-то случилось), false (ничего не произошло) и undef (ошибка произошла).
, а не поговорка
use strict;
use warnings;
, скажем
use common::sense;
, и вы получите все преимущества предупреждений, но с раздражающими, как неопределенные переменные.
Common :: Sense доступен от CPAN.
Пока что найденные мной дела..:
if $foo
или $foo || $bar
++
или --
+=
, -=
, или . =
-=
.