Это одно из самых распространенных предупреждений, которые встречаются, когда запускаешь Perl-код.

Это предупреждение, так что оно не помешает вашему скрипту выполниться, и оно выдается только если предупреждения были включены. (Что рекомендуется делать)

Обычно предупреждения включают с помощью выражения use warnings; в начале вашего скрипта или модуля.

Старый способ - добавить флаг -w в консоли. Обычно так выглядит первая строка такого скрипта:

#!/usr/bin/perl -w

Существуют некоторые различия, но, поскольку use warnings доступно на текущий момент вот уже 12 лет, нет причины избегать его. Другими словами:

Всегда используйте use warnings;!

Теперь давайте вернемся собственно к тому предупреждению, значение которого мы хотели объяснить в этой статье.

Быстрое объяснение

Use of uninitialized value $x in say at perl_warning_1.pl line 6.

Это значит, что у переменной $x нет значения (ей присвоено специальное значение undef). Либо у нее и не было никакого значения, либо в какой-то момент ей присвоили значение undef.

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

Простой пример

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

use warnings;
use strict;
use 5.010;

my $x;
say $x;

Perl сообщит нам, в каком файле и на какой строке возникло это предупреждение (очень мило с его стороны).

Лишь предупреждение

Как уже упоминалось, это лишь предупреждение. Если в скрипте есть еще выражения после этого say, они будут выполнены.

use warnings;
use strict;
use 5.010;

my $x;
say $x;
$x = 42;
say $x;

Результат выполнения этого кода:

Use of uninitialized value $x in say at perl_warning_1.pl line 6.

42

Смущающий порядок вывода

Однако будьте внимательны, если в вашем коде есть выражения print до строки, выдающей предупреждение, как в этом примере:

use warnings;
use strict;
use 5.010;

print 'OK';
my $x;
say $x;
$x = 42;
say $x;

результат может вас смутить.

Use of uninitialized value $x in say at perl_warning_1.pl line 7.
OK
42

Здесь мы видим вывод 'OK' после предупреждения, хотя вызов

print

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

Эта странность - результат

Буферизации ввода-вывода

. По умолчанию Perl буферизирует STDOUT, стандартный канал вывода, но не STDERR, стандартный канал для ошибок.

Так что, пока 'OK' ждет высвобождения буфера, предупреждение уже выводится на экран.

Выключение буферизации

Чтобы избежать этого, вы можете выключить буферизацию STDOUT.

Это можно сделать, добавив такой код: $| = 1; в начало скрипта.

use warnings;
use strict;
use 5.010;

$| = 1;

print 'OK';
my $x;
say $x;
$x = 42;
say $x;

OKUse of uninitialized value $x in say at perl_warning_1.pl line 7.
42

(Предупреждение на одной строке с OK, потому что мы не вывели символ перевода строки \n после 'OK'.)

Нежелательная область видимости

use warnings;
use strict;
use 5.010;

my $x;
my $y = 1;

if ($y) {
  my $x = 42;
}
say $x;

Этот код также выдает предупреждение Use of uninitialized value $x in say at perl_warning_1.pl line 11.

Я умудрился сделать эту ошибку несколько раз. Я не обратил внимания на то, что написал my $x внутри блока, чем создал новую переменную $x, присвоил ей значение 42 и позволил ей исчезнуть в конце блока. ($y = 1 это просто замещение некоего настоящего кода с настоящим условием, чтобы пример выглядил пореалистичнее.)

Конечно, существуют случаи, когда нужно объявить переменную внутри блока, но не всегда. Когда это происходит по ошибке, поиск бага бывает очень болезненным.