Как-то совсем давно я ничего не писал, думаю уже пора :). Не так давно прошла конференция BlackPerl 2011. Я думаю, что уже многие в курсе относительного этого события.
Я на конференцию ехал без доклада, просто с желанием познакомится с Perl-комьюнити, послушать других и пофотографировать сие действо. Но вдохновленный докладчиками, решил и сам соорудить небольшое выступление. Поскольку, конкретной темы у меня не было, я решил просто рассказать про интересные вещи в Perl. Ничего особенного, но возможно кто-то найдет для себя что-то новое.
Приступим.
Недостаток такого подхода в том, что caller будет нам возвращать "__ANON__" в качестве имени нашего метода. И stack trace будет нечитабельным.
Это проблему призван решить модуль "Sub::Name" , он позволяет давать имена анонимным функциям. Эти имена будут показываться в стеке вызовов, но их нельзя использовать для вызова функции/метода.
Наш пример приобретет вид:
Вы встречали такой код - "$sth->execute() or die;" , а задумывались как он может работать, если "execute" возвращает количество измененных рядков для не "select" запросов. Ведь если по условию WHERE при UPDATE мы не нашли ничего, то это ж не является ошибкой. Получается, что метод возвращает нулевое истинное значение.
И вот самый интересный вариант нулевого истинного значения:
Просто несколько нюансов при работе с функцией local
В Perl есть файловый хендлер ARGV, с которого мы можем вычитать файлы переданные скрипту в качестве аргументов командной строки. В примере происходит следующее:
1. Мы помещаем имя файла в массив @ARGV, который должен содержать переданные скрипту аргументы
2. Локализируем "$/" значением undef
3. Вычитываем файл в переменную
При этом, можно вычитать несколько файлов одним потоком:
Детали можно прочитать в "perldoc -f require"
Причина в том, что Perl на место пустого регекспа поставит последний удачно совпавший регексп.
export PERL5OPT='-MData::Dumper'
И затем всегда Data::Dumper будет доступен в ваших однострочниках:
perl -e 'print Dumper([1,2])'
В посте "Чем плох eval?!" были описаны проблемы перехвата исключений в Perl и я рекомендовал использовать модуль "Try::Tiny". Но с "Perl 5.14" необходимость в "Try::Tiny" практически отпала, это было описано в посте "Наконец-то исправлена обработка исключений в Perl 5.14"
Я на конференцию ехал без доклада, просто с желанием познакомится с 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/
Я так понимаю, что это мы просто зададим имя для всех анонимных функций. Хотелось бы увидеть как Вы реализуете аналогичное такому:
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 же).
> Имя задается не для всех анонимных функций, а для текущей выполняемой (local же).
local позволяет нам лишь временно задать имя в пределах некого блока, но имя будет актуально для всех анонимных функций( если они не переопределят его уже сами ). По этой причине caller и не работает, как мы хотим.
Отправить комментарий
Не забудьте добавить себя в постоянные читатели и включить уведомления о новых комментариях, либо воспользуйтесь RSS каналом ;)