среда, 26 октября 2011 г.

Интересности Perl

Как-то совсем давно я ничего не писал, думаю уже пора :). Не так давно прошла конференция BlackPerl 2011. Я думаю, что уже многие в курсе относительного этого события.
Я на конференцию ехал без доклада, просто с желанием познакомится с Perl-комьюнити, послушать других и пофотографировать сие действо. Но вдохновленный докладчиками, решил и сам соорудить небольшое выступление. Поскольку, конкретной темы у меня не было, я решил просто рассказать про интересные вещи в Perl. Ничего особенного, но возможно кто-то найдет для себя что-то новое.

Приступим.

Приватные методы
В Perl возможно реализовать приватные методы и делается это следующим образом:

Недостаток такого подхода в том, что caller будет нам возвращать "__ANON__" в качестве имени нашего метода. И stack trace будет нечитабельным.


Это проблему призван решить модуль  "Sub::Name" , он позволяет давать имена анонимным функциям. Эти имена будут показываться в стеке вызовов, но их нельзя использовать для вызова функции/метода.

Наш пример приобретет вид:


Истина или Ложь

Вы встречали такой код - "$sth->execute() or die;" , а задумывались как он может работать, если "execute" возвращает количество измененных рядков для не "select" запросов. Ведь если по условию WHERE при UPDATE мы не нашли ничего, то это ж не является ошибкой. Получается, что метод возвращает нулевое истинное значение.



И вот самый интересный вариант нулевого истинного значения:


Локализируемся

Просто несколько нюансов при работе с функцией local


Однострочник для чтения файла

В Perl есть файловый хендлер ARGV, с которого мы можем вычитать файлы переданные скрипту в качестве аргументов командной строки. В примере происходит следующее:
1. Мы помещаем имя файла в массив @ARGV, который должен содержать переданные скрипту аргументы
2. Локализируем "$/" значением undef
3. Вычитываем файл в переменную

При этом, можно вычитать несколько файлов одним потоком:


@INC
Многие знают, что массив @INC содержит список путей, которые Perl использует для поиска подключаемых модулей. Но кроме путей @INC может содержать хуки в виде ссылки на функцию, объект, массив. В прагме "use everywhere" используется данная возможность.

Детали можно прочитать в "perldoc -f require"


Осторожно! Пустой регексп
Я думаю многих удивит результат выполнения такого вот кода:



Причина в том, что Perl на место пустого регекспа поставит последний удачно совпавший регексп.


Переменная по-умолчанию



Переменные окружения
Многие используют переменную окружения PERL5LIB для указания пути к перловым модулям. Но кроме этой переменной окружения есть еще PERL5OPT, позволяющая задать опции командной строки, которые передаются интерпретатору Perl при запуске. Например, можно подключить определенные модули:
export PERL5OPT='-MData::Dumper'
И затем всегда Data::Dumper будет доступен в ваших однострочниках:
perl -e 'print Dumper([1,2])'

Try::Tiny
Этот момент я освещал уже в своем блоге.
В посте "Чем плох eval?!" были описаны проблемы перехвата исключений в Perl и я рекомендовал использовать модуль "Try::Tiny". Но с "Perl 5.14" необходимость в "Try::Tiny" практически отпала, это было описано в посте "Наконец-то исправлена обработка исключений в Perl 5.14"

Материалы по конференции

5 коммент.:

Анонимный комментирует...

Давать именам анонимным сабрутинам очень просто:
local *__NAME__ = 'subname'

Анонимный комментирует...

s/NAME/ANON/

koorchik комментирует...

Я так понимаю, что это мы просто зададим имя для всех анонимных функций. Хотелось бы увидеть как Вы реализуете аналогичное такому:

use v5.10;
use Sub::Name;
my $name1 = subname name1 => sub {
say( (caller(0))[3] );
say( (caller(1))[3] );
say( (caller(2))[3] );
};
my $name2 = subname name2 => sub { $name1->() };
my $name3 = subname name3 => sub { $name2->() };
$name3->();

# Результат будет таким
#main::name1
#main::name2
#main::name3

Анонимный комментирует...

По стеку вызовов с такой конструкцией ходить не получится, да.
Имя задается не для всех анонимных функций, а для текущей выполняемой (local же).

koorchik комментирует...

> Имя задается не для всех анонимных функций, а для текущей выполняемой (local же).
local позволяет нам лишь временно задать имя в пределах некого блока, но имя будет актуально для всех анонимных функций( если они не переопределят его уже сами ). По этой причине caller и не работает, как мы хотим.

Отправить комментарий

Не забудьте добавить себя в постоянные читатели и включить уведомления о новых комментариях, либо воспользуйтесь RSS каналом ;)