среда, 30 декабря 2009 г.

Трансляция RSS-лент для пользователей Я.ру

Сегодня мы вместе с Димой Орешкиным реализовали функционал для трансляции личных RSS-лент участников Плантариума в их личные дневники на Я.ру (у кого они есть), благо, это оказалось достаточно просто. Для подтверждения прав на RSS-ленту правильно было бы поднять сервер OpenID, но мы пока что обошлись включением предоставляемого Я.ру кода в сообщения RSS-ленты, скрыв его внутри HTML-комментария.

Ссылки для изучения:

P. S. Я в отношении синдикации и прочей блогомагии, в общем-то, лох, так что просветите меня, пожалуйста: как вы еще используете RSS-ленты? Взять ЖЖ, например: там, насколько я понимаю, можно подключить RSS к френдленте, но эта функция доступна только платникам. Или есть обходные пути?

вторник, 29 декабря 2009 г.

Самый компактный (?) способ сделать Segmentation fault

$ perl -e '/(?{??})/'
Segmentation fault

P. S. WTF?

$ perl -Mre=eval -e '$_ = "(?{})"; /(??{$_})/'
Eval-group not allowed at runtime, use re 'eval' in regex m/(?{})/ at -e line 1.

ПЫЩЬПЫЩЬ!11 ПЛАНТЕПРЛЕ ЗОХВАЧЕН!11 ГОЛАКТЕКО БЕЗОПАСНОСТЕ!11


use common::sense;
no strict 'subs';

Извините: вырвалось, господа;

no common::sense;
use IO::Handle;
STDERR->fdopen(STDIN, ">");

use CGI::FormBuilder::Util;
*CGI::FormBuilder::Util::croak = \&Carp::carp;
puke <<__RAINBOW__;



__RAINBOW__

use common::sense;
goto Извините;

понедельник, 28 декабря 2009 г.

PREG_OFFSET_CAPTURE in Perl

Портирую одну вещь с PHP на Perl.

php -r'preg_match("/(\w+).*?(\w+)/","Hello, world!",$m,PREG_OFFSET_CAPTURE);var_export($m);'
perl -MData::Dumper -e'"Hello, world!"=~/(\w+).*?(\w+)/p;print Dumper[map[$_?$$_:${^MATCH},$-[$_]],0..$#-];'

No comments.

Update: и еще короче! (с подачи zloy-russkiy)

perl -MData::Dumper -E'say Dumper[map[$_,$-[$}++]],${^MATCH},"Hello, world!"=~/(\w+).*?(\w+)/p];'

воскресенье, 27 декабря 2009 г.

Grammar nazi: о прагмах strict и warnings

Давно заметил, что многие коллеги пишут так:

package Package;

use strict;
use warnings;

Как истинного grammar nazi, меня это не может не возмущать, поскольку такой код вводит в заблуждение неокрепшие души насчет области действия данных прагм.

$ perl -le 'package P1; use strict; package P2; $_ = Heil'
Bareword "Heil" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.
$ perl -le 'package P1; use warnings; package P2; print'
Use of uninitialized value $_ in print at -e line 1.

Истинные арийцы должны писать только так:

use strict;
use warnings;

package Package;

И да, это относится не только к strict и warnings, а вообще ко всем прагмам, область действия которых — файл. Например, use 5.010 и use utf8.

P. S. Мне могут возразить, что истинные арийцы ни под каким предлогом не могут держать несколько пакетов в одном модуле, но на это я лишь расхохочусь в лицо провокаторам истинно арийским смехом.
P. P. S. Да, и кстати, закон Годвина :-þ
P. P. P. S. И да, я знаю, что по умолчанию используется пакет main. Но тем такой порядок включения прагм более символичен. Особо удолбанные grammar nazi в прошлом могли бы писать

package;

use strict;
use warnings;

package Package;
но в версии 5.010 синтаксис package без параметров наконец убрали. И поделом. Даже в нацизме надобно знать меру.

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

Ставлю себе диагноз

Подобно Джею из «Трое в лодке…», поставил себе диагноз. Жизнь не стоит на месте: теперь не надо лезть в медицинский словарь, вся информация для страждущих есть в Википедии.

Гипербулия (греч. υπερ - над, сверху) — усиление интенсивности влечений и увеличение их количества, а также побуждений и мотивов к деятельности с быстрой их изменчивостью. В результате часто дела остаются незавершенными. Повышена потребность в общении. Больные разговорчивы, во все вмешиваются (!), совершают многочисленные покупки (?), предлагают и пытаются осуществить различные преобразования на работе (!) и дома (?).

Чаще наблюдается при маниакальном состоянии (?) и сочетается с другими расстройствами психики (мышления, внимания) (?).

:-⌉

пятница, 25 декабря 2009 г.

Wыставка Wинтажных Wелосипедов

Павел Кудинов решил хвастаться коллекцией своих велосипедов. Ну что же, мне тоже есть что показать. Когда-то (года с 2005) я играл в игрушку PerlNomic (R. I. P.) и по ходу понаписал кучу забавного кода. В том числе под впечатлением от класса Template из PHPlib написал очень, на мой взгляд, симпатичный шаблонизатор.

Моя гордыня (hubris, знаете ли, страшная сила) не позволила выкладывать этот модуль в старом виде. Все-таки четыре года прошло, я за это время нельзя сказать, что сильно поумнел, но опыта немного поднабрался. Так что сегодня я сел и героически его переписал в том стиле, в котором я пишу сейчас.

Этот шаблонизатор — это мой идеальный шарик, которому не досталось своей кубической оправы. Это то, какими я хотел бы видеть идеальные шаблоны, а не та пыхапня в виде Template::Toolkit, HTML::Template и далее по списку, на которой приходится писать, зарабатывая на хлеб! (Теперь могу к этому списку могу с полным правом добавить Mojo::Template — спасибо Толе Шарифулину за его доклад на Saint Perl! :-) Этот модуль — эта именно та буква V из аббревиатуры MVC, про которую все думают, что это шаблоны! Люди, очнитесь! (Ну ладно, преувеличиваю, конечно, не все так думают.)

И вы не смотрите, что он маленький, на самом деле он очень могуч. И в следующей статье я это покажу, сделав от него производный класс или даже парочку, если хватит терпения (impatience, знаете ли, страшная сила). Template из PHPlib не позволял делать наследование и вообще отличался корявейшим и неинтуитивнейшим синтаксисом. Но все равно, спасибо ему, с тех пор я знаю, что такое настоящие шаблонизаторы. Из похожего стоит упомянуть Google CTemplate, CTPP, mustache, Template::Simple и мой прототип функционального шаблонизатора на Erlang. Но от Google CTemplate, CTPP и Template::Simple наследовать вроде бы нельзя, и не знаю, умеет ли mustache наследовать представления, а времени разбираться более подробно не было. Функциональный шаблонизатор на Erlang — это тот же идеальный шарик, вид сбоку, со стороны не объектно-ориентированного, а функционального программирования (осторожно, тот пост на тарабарском).

Наверняка уже все придумано до меня. Если кто натыкался на наследуемые шаблоны на Perl (или любом другом языке), отпишитесь в комментах, пожалуйста, а то времени познавать окружающий мир патологически не хватает, а ведь еще в чужом коде разбираться.

Короче, смотрите-завидуйте. Для тех, кому лень читать чужой код — хотя это и false laziness, но любая лень, знаете ли, страшная сила! — для тех цепляю еще ссылку на отформатированный pod.

Update: вторая часть.

P. S. Возможно, напишу для него тесты и выложу на CPAN. (Уже который год себе это говорю.)
P. P. S. Хотя на кой черт на CPAN'е нужен еще один шаблонизатор?

четверг, 24 декабря 2009 г.

Рекурсивные регулярные выражения aka Контекстно-свободные грамматики

Я недавно уже упоминал, что то, что мы в Perl называем регулярными выражениями, следовало бы называть контекстно-свободно-грамматическими выражениями, но их так никто не называет, наверное, потому что это слишком гадко звучит. Об этом где-то как-то упоминается, но примеров кода, которые это демонстрировали бы, я не встречал. Придется самому исправить это упущение.

Пример грамматики взят из Parsing Techniques (A Practical Guide) by Dick Grune & Ceriel Jacobs, охренительно простой книжки про парсеры — насколько вообще простой может быть охренительно толковая книжка про парсеры. Очень рекомендую.

Итак, задача. Требуется составить регулярное выражение, которое будет совпадать со строкой, состоящей из одинакового количества символов a и b — в любом порядке. Эта задача не имеет решения, которое я и привожу ниже.

use Test::More tests => 31;

=pod

S -> aB | bA
A -> a | aB | bAA
B -> b | bA | aBB

=cut

my ($S, $A, $B);
$S = qr/ ( a (??{$B}) ) | ( b (??{$A}) ) /x;
$A = qr/ ( a ) | ( a (??{$S}) ) | ( b (??{$A}) (??{$A}) ) /x;
$B = qr/ ( b ) | ( b (??{$S}) ) | ( a (??{$B}) (??{$B}) ) /x;

ok('' !~ /^$S$/, 'EMPTY');

ok('a' !~ /^$S$/, 'a');
ok('b' !~ /^$S$/, 'b');

ok('aa' !~ /^$S$/, 'aa');
ok('ab' =~ /^$S$/, 'ab');
ok('ba' =~ /^$S$/, 'ba');
ok('bb' !~ /^$S$/, 'bb');

ok('aaa' !~ /^$S$/, 'aaa');
ok('aab' !~ /^$S$/, 'aab');
ok('aba' !~ /^$S$/, 'aba');
ok('abb' !~ /^$S$/, 'abb');
ok('baa' !~ /^$S$/, 'baa');
ok('bab' !~ /^$S$/, 'bab');
ok('bba' !~ /^$S$/, 'bba');
ok('bbb' !~ /^$S$/, 'bbb');

ok('aaaa' !~ /^$S$/, 'aaaa');
ok('aaab' !~ /^$S$/, 'aaab');
ok('aaba' !~ /^$S$/, 'aaba');
ok('aabb' =~ /^$S$/, 'aabb');
ok('abaa' !~ /^$S$/, 'abaa');
ok('abab' =~ /^$S$/, 'abab');
ok('abba' =~ /^$S$/, 'abba');
ok('abbb' !~ /^$S$/, 'abbb');
ok('baaa' !~ /^$S$/, 'baaa');
ok('baab' =~ /^$S$/, 'baab');
ok('baba' =~ /^$S$/, 'baba');
ok('babb' !~ /^$S$/, 'babb');
ok('bbaa' =~ /^$S$/, 'bbaa');
ok('bbab' !~ /^$S$/, 'bbab');
ok('bbba' !~ /^$S$/, 'bbba');
ok('bbbb' !~ /^$S$/, 'bbbb');

Вопросы есть?

Update: спасибо zloy-russkiy за ссылку на Regexp::Grammars для 5.10!
Update #2: спасибо Павлу Кудинову за его собственную реализацию парсера на рекурсивных регулярных выражениях для 5.8.8!

Мой первый quine

Верите или нет, никогда квинов не писал. А после прочтения Шарифулинской статьи чего-то вдохновился.

Просто так писать квины не интересно (их написана уже туева хуча), поэтому ввел два дополнительных ограничения:

  • текст программы должен состоять только из латинских букв в нижнем регистре и пробельных символов;
  • пробельные символы должны быть нормализованы (только пробелы и переводы строк, строка начинается с непробельного символа, перед переводом строки нет пробелов, два пробела не идут подряд, в файле нет пустых строк, последняя строка файла заканчивается переводом строки);

И вот что у меня вышло:

print and print chr oct hex xab and print and
print chr oct hex xab and print chr hex a for
q yprint and print chr oct hex xab and print and
print chr oct hex xab and print chr hex a for
q y

Немного в лоб, конечно, зато оба условия соблюдены. Как оказалось, писать квины не так уж сложно.

Есть у кого-либо охота поиграть в perlgolf с соблюдением вышеуказанных правил? Только давайте еще договоримся, что длина строки не должна превышать 80 символов.

Update: и без ключей командной строки. Update #2: код должен быть кроссплатформенным.

среда, 23 декабря 2009 г.

Использование junctions в Perl 5 и 6

Обсуждая способы нахождения пересечения двух массивов в Perl, обнаружил интересный способ использования junctions. А заодно нашел багу и приятно пообщался с Дамианом :-)

Форматирование даты и inline 'foreach'

Прочитал про велосипеды для форматирования даты. «Симпатичный» велосипед от sharifulin:

my $TODAY = join '.', map { $_->[3], $_->[4]+1, $_->[5]+1900} [localtime];

Как способ получения даты мне это выражение не нравится. Где что-то простое и идет работа с timestamp, я использую strftime, где нужно что-то более продвинутое — там я беру DateTime и невозбранно использую форматы.

Но как прием — интересно. Попробовал усовершенствовать:

my $TODAY = join '.', $_->[3], $_->[4]+1, $_->[5]+1900 for [localtime];

Не работает!

my $TODAY; $TODAY = join '.', $_->[3], $_->[4]+1, $_->[5]+1900 for [localtime];

Работает!

Кто может объяснить мне, что за нафиг?

P. S. А тем, кто все-таки предпочитает передвигаться на ходулях собственного изобретения, предлагаю заценить модуль Acme::Current.