4 Несвязанные с Perl мелочи

Недавно я приобрел копию книги «Программирование Perl», которую в сообществе Perl часто называют «Верблюжьей книгой». Прочитав первые 4 главы, я решил поделиться несколькими интересными для меня моментами, связанными с Perl.

While <> is True

Допустим, у нас есть следующий файл с именем logos.txt.

Onion
Camel

Raptor
Войти в полноэкранный режим Выйти из полноэкранного режима

И в той же директории у нас есть следующая программа scratch.pl.

open my $fh, '<', 'logos.txt' or die;
while (my $logo = <$fh>) {
    print $logo;
}
close $fh;
Войти в полноэкранный режим Выйти из полноэкранного режима

Как и ожидалось, наша программа печатает содержимое файла logos.txt.

$ perl ./scratch.pl
Onion
Camel

Raptor
Вход в полноэкранный режим Выход из полноэкранного режима

Однако я никогда не задумывался над тем, почему цикл не завершается, когда <> считывает пустую строку в logos.txt? Разве <> не должен возвращать пустую строку, которая является ложным значением?

Согласно Programming Perl, причина, по которой цикл не завершается, заключается в том, что <> считывает новую строку в конце строки, поэтому мы получаем "n", что является истинным значением. Оказывается, это обман, и на самом деле причина в том, что while (my $logo = <$fh>) ... расширяется в while (defined (my $logo = <$fh>)) ..., а "n" — это определенное значение.

Мы можем показать это, департировав код с помощью B::Deparse.

$ perl -MO=Deparse,-p,-sCi2 -ne 42
LINE: while (defined(($_ = readline(ARGV)))) {
  '???';
}
-e syntax OK
Вход в полноэкранный режим Выход из полноэкранного режима

Heredocs может выполнять команды оболочки

Большинство программистов на Perl знают, что если заключить завершающую строку heredocs в одинарную кавычку, то это предотвратит интерполяцию переменных.

my $var = 12;
print <<'EOS';
Hello
$var = 12
EOS
Войти в полноэкранный режим Выход из полноэкранного режима

В выводе программы видно, что $var не была интерполирована.

$ perl ./scratch.pl
Hello
$var = 12
Вход в полноэкранный режим Выход из полноэкранного режима

Но знаете ли вы, что если заключить завершающую строку в обратную кавычку, то каждая строка будет выполняться как команда оболочки?

print <<`EOC`;
echo this is a shell command
echo this is also a shell command
EOC
Вход в полноэкранный режим Выход из полноэкранного режима

Запустив эту программу, мы видим, что команды echo были выполнены.

$ perl ./scratch.pl
this is a shell command
this is also a shell command
Войти в полноэкранный режим Выход из полноэкранного режима

Оператор запятая

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

Вы когда-нибудь задумывались, почему списки возвращают свой последний элемент при скалярной оценке? Оказывается, это связано с оператором запятой.

В скалярном контексте оператор запятой «,» игнорирует свой первый аргумент и возвращает второй элемент, оцененный в скалярном контексте.

Это означает, что в скалярном контексте список (11, 22, 33) будет иметь значение 33. Первый оператор запятой отбросит 11, а затем вернет (22, 33), оцененный в скалярном контексте, который будет оценен, отбросив 22 и вернув 33.

Автоинкрементные строки

В perl можно автоматически увеличивать не только числа, но и строки. Чтобы увеличить строку, она должна соответствовать regex /^[a-zA-Z]*[0-9]*z/.

Строки из символов одного алфавита увеличиваются интуитивно.

$ perl -E 'my $v = "a"; say ++$v'
b
$ perl -E 'my $v = "B"; say ++$v'
C
Вход в полноэкранный режим Выход из полноэкранного режима

Что произойдет, если мы увеличим не алфавитно-цифровой символ. Выдаст ли он следующий символ ASCII? Оказывается, при инкрементировании неалфавитно-цифровые символы рассматриваются как 0. К счастью, если мы используем предупреждения, Perl предупредит нас об этом.

$ perl -W -E 'my $v = "-"; say ++$v'
Argument "-" treated as 0 in increment (++) at -e line 1.
1
Вход в полноэкранный режим Выход из полноэкранного режима

Что произойдет, если мы увеличим z, который находится в конце алфавита? Вернемся ли мы обратно к a? Вот здесь все становится интересным. Perl увеличивает строку так же, как и в обычной системе счисления. Так же, как 9 + 1 = 10 в десятичной z + 1 = aa в … строчной.

$ perl -E 'my $v = "z"; say ++$v'
aa
Вход в полноэкранный режим Выход из полноэкранного режима

Вот еще несколько примеров, демонстрирующих магию автоинкрементирования строк.

$ perl -W -E 'my $v1 = "foo"; say ++$v1'
fop
$ perl -W -E 'my $v1 = "az"; say ++$v1'
ba
$ perl -W -E 'my $v1 = "a9"; say ++$v1'
b0
Вход в полноэкранный режим Выход из полноэкранного режима

Оцените статью
devanswers.ru
Добавить комментарий