use strict и use warnings

Если открыть почти любой Perl-скрипт, написанный за последние двадцать лет — учебный пример, код коллеги, библиотеку с открытым исходным кодом, — в первых же строках почти наверняка найдутся две строчки:

use strict;
use warnings;

Это не какая-то формальность и не «магическое заклинание для порядка». Это две директивы, которые заставляют Perl гораздо строже проверять твой код и честно сообщать об ошибках, вместо того чтобы молча делать что-то не то. Без них Perl — на удивление снисходительный язык: он готов выполнить код с опечатками, необъявленными переменными и другими проблемами, просто получая на выходе неверный результат без единого предупреждения.

Зачем это нужно в языке

Perl создавался в конце восьмидесятых как язык для быстрых однострочных скриптов — «напиши, запусти, выброси». Ради этой цели он изначально очень многое прощает: можно использовать переменную, не объявляя её заранее, можно опечататься в имени переменной, и Perl просто создаст новую переменную с этим опечатанным именем, ничего не спросив. Для короткого одноразового скрипта это удобно. Но стоит написать хотя бы сто строк кода, и та же снисходительность превращается в кошмар: опечатка в имени переменной не выдаёт ошибку при запуске, а просто тихо портит результат где-то в середине программы, и найти причину бывает очень трудно.

use strict и use warnings — это способ включить в Perl «строгий режим», где такие ситуации сразу становятся видимыми ошибками или явными предупреждениями, а не тихими сюрпризами.

Синтаксис с примером

Вот один и тот же код с ошибкой — сначала без этих директив, потом с ними:

# Без use strict — программа запустится
$naem = "Аня";
print "Привет, $name!\n";

Вывод:

Привет, !

Заметил опечатку? В первой строке переменная называется $naem (буквы перепутаны местами), а во второй используется $name. Это две совершенно разные переменные с точки зрения Perl. Без use strict программа не упадёт — она просто выведет пустое значение вместо имени, и без внимательного чтения кода эту ошибку легко пропустить.

Теперь тот же код, но с директивами в начале:

use strict;
use warnings;

$naem = "Аня";
print "Привет, $name!\n";

Вывод:

Global symbol "$naem" requires explicit package name at script.pl line 4.
Global symbol "$name" requires explicit package name at script.pl line 5.
Execution of script.pl aborted due to compilation errors.

Теперь Perl отказывается запускать скрипт вообще и прямо указывает номера строк с проблемой. Это выглядит как «более сложный» результат, но на самом деле это подарок: ошибка нашлась за секунду, а не после часа поиска в логах, почему в отчёте пропало имя пользователя.

Разбор построчно

use strict; — включает три проверки сразу. Главная для новичка: каждая переменная теперь обязана быть объявлена через my перед использованием. Если написать $naem = "Аня"; без my $naem = "Аня";, Perl сочтёт это ошибкой ещё до запуска программы, а не тихо создаст новую переменную.

use warnings; — включает вывод предупреждений о подозрительных, но не обязательно ошибочных ситуациях: использование неинициализированного значения (undef) в арифметике или строке, сравнение строки с числом там, где это выглядит случайным, и другие похожие мелочи. Такие ситуации не останавливают программу, но выводят предупреждение в текстовый поток ошибок, чтобы ты о них узнал.

Обе директивы обычно пишут вместе и именно в первых строках файла — до любого другого кода, — чтобы проверки действовали на весь скрипт целиком.

Практический пример

Вот ситуация, где use warnings ловит реальную логическую ошибку, а не просто опечатку в имени:

use strict;
use warnings;

my %prices = (
    "хлеб"   => 45,
    "молоко" => 80,
);

my $total = $prices{"хлеб"} + $prices{"сыр"};
print "Итого: $total\n";

Вывод:

Use of uninitialized value in addition (+) at script.pl line 8.
Итого: 45

Ключа "сыр" в хеше %prices нет, поэтому $prices{"сыр"} равен undef. Без use warnings программа так же тихо посчитала бы 45, как будто сыр стоит ноль рублей, и ты бы никогда не узнал, что что-то пошло не так. С use warnings Perl прямо говорит: «здесь используется неинициализированное значение», и это явный сигнал проверить логику.

Частые ошибки

Самая распространённая ошибка — не подключать эти директивы вовсе, особенно в учебных или «быстрых» скриптах, а потом переносить тот же код в более серьёзный проект без изменений. Проблема в том, что баги, которые прячет отсутствие use strict, почти всегда всплывают в самый неудобный момент — когда скрипт уже используется кем-то другим.

Вторая ошибка — добавить только одну из двух директив. use strict без use warnings ловит необъявленные переменные, но пропускает предупреждения о undef и подозрительных сравнениях. use warnings без use strict ловит часть подозрительных ситуаций, но всё ещё разрешает опечатки в именах переменных. Их всегда используют вместе.

Третья ошибка — воспринимать предупреждения от use warnings как что-то необязательное, что можно игнорировать. На практике почти каждое предупреждение указывает на реальную проблему в логике программы, даже если сама программа не падает.

Итоги

use strict и use warnings превращают снисходительный по умолчанию Perl в язык, который честно сообщает о проблемах вместо того, чтобы молча выдавать неверный результат. use strict требует объявлять переменные через my и ловит опечатки в именах ещё до запуска программы. use warnings предупреждает о подозрительных ситуациях вроде использования undef. Эти две строки — первое, что стоит написать в любом Perl-скрипте длиннее одной команды.

Проверьте себя
1. Что делает use strict, если в коде используется переменная без предварительного объявления через my?
AНичего — просто выводит предупреждение в конце работы программы
BАвтоматически объявляет её как глобальную и продолжает работу
CОстанавливает программу ошибкой ещё до её запуска
DЗаменяет переменную на undef без сообщений
2. Чем use warnings отличается от use strict?
AЭто два названия одной и той же директивы
Buse warnings выводит предупреждения о подозрительных ситуациях (например, undef в вычислениях), но не останавливает программу, а use strict останавливает выполнение при необъявленных переменных
Cuse warnings нужен только для работы с файлами
Duse strict работает лишь в старых версиях Perl