Грабля Perl кода my $success = false;

Только что наступил на замечательную проблему в Perl.

Я очень люблю использовать модуль boolean. Т.е я бычно пишу что-то вроде:

use boolean;

...

my $has_orders = true;

Я люблю явно писать true/false, а не использовать всякие другие значения (типа 1/0, 1/''), которые Perl в булевом контексте будет интерпритировтаь как boolean. Я считаю что явное использование true/false упрощает чтение програмы. Сразу видно что это значение boolean, а не число или строка. Если не использовать этот модуль, то пример выше выглядит вот так:

my $has_orders = 1;

При чтении этого кода можно задаться вопросом "единица — что это такое? Это true значение или это количество заказов?" Для того чтобы распарсить эту строку нужно смотреть на то как дальше испольузется эта переменная.

Так а теперь про проблему. В одном скрипте я написал нечто вроде:

my $success = false;

if ( condition() ) {
    $success = true;
}

if ($success) {
    do_some_work();
}

Оказалось, что do_some_work() выполяется во всех случаях, вне зависимости от того что возвращает condition().

Решение оказалось элементарное. Оказывается, я забыл написать "use boolean;" поэтому false без кавычек интерпритировалась как строка "false", а такая строка — это true значение.

На эту граблю я наступил только из-за того что в моем скрипте не было "use strict;" — это был очень маленький скрипт, который я быстро написал и посчитал (ошибочно), что там все так просто что дополнительные проверки не нужны. Если бы у меня был "use strict;" то при запуске скрипта я сразу же получил внятные ошибки:

Bareword "false" not allowed while "strict subs" in use at a.pl line 12.
Bareword "true" not allowed while "strict subs" in use at a.pl line 15.
Execution of a.pl aborted due to compilation errors.

Так что узелок на память — во всех скриптах всегда использовать:

use strict;
use warnings FATAL => 'all';

Иван Бессарабов
ivan@bessarabov.ru

5 августа 2014