Free / gratitudo / libero

Тот факт, что Perl был создан лингвистом, не мог не надожить отпечаток и на пользователей языка. Довольно часто разговоры между любителями перла перетекают на обсуждение языков. Не языков программирования, а языков человеческих.

В итальянской монгерской рассылке, например, прошло небольшое обсуждение того, что английской слово free неоднозначно. Неоднозначность вызвана тем, что, как и в русском языке, это слово может переводиться и как свободный, и как бесплатный.

Даккар приводит такие примеры:

VMWare Server è *gratuito*. (VMWare Server бесплатный.)

VirtualBox e qemu sono *liberi*. (VirtualBox и qemu свободные.)

К сожалению, читать итальянскую рассылку mongers@lists.perl.it можно только «вживую», веб-архива у нее нет.

Padre

Вчера вышло очередное обновление написанной на перле интегрированной среды Padre.

Сейчас все работает и под Windows, и под Mac OS. Есть и русский перевод (я его обновлю на днях).

А то, что размер дистрибутива 40 МБ, не должно сильно смущать: в комплекте идут все необходимые компоненты, включая сам Strawberry Perl. Надеюсь, что со временем такого избыточного комплекта не потребуется.

Где можно увидеть Тима Банса

Tim Bunce — автор модуля DBI — 12 и 13 октября приезжает в Москву, чтобы выступить на конференции HighLoad++.

На вечер 12 октября (понедельник) в «Инфопространстве» запланирована встреча с Moscow.pm. Начало в 19 часов, вход свободный.

Кроме того, Тима в ближайшее время можно увидеть на пятом итальянском Perl-воркшопе в Пизе 22 и 23 октября.

Один из докладов, с которыми он собирается выступить, — Perl Myths. В рассылках про Perl 6 и Parrot сейчас идет обсуждение о том, чем стоит дополнить существующий материал.

О сложности и простоте

На прошлой неделе мне потребовалось автоматически постить RSS в Твиттер.

Первая мысль была — использовать Plagger. Тем более, что именно эту программу ребята использовали на январском хакмите в Москве.

Plagger — это такой механизм, где с помощью конфигурации (в YAML) формируется цепочка, через которую проходят новости, собираемые из разных источников. Всю обработку ведут отдельные плагины: один забирает RSS, другой фильтрует данные, третий размещает их в Твиттере, отправляет по почте или складывает в XML-файлы. Конфигурация может быть самой замысловатой, а отдельных плагинов больше сотни.

Установка оказалась весьма муторной, заняла часа полтора и скачала пол-спана. К тому же, не очень понятно (а документации — кот наплакал), как не пропускать дубликаты записей и как заставить плагины сохранять результаты в базе данных. Необъятное число необходимых модулей заставило задуматься о том, насколько сложно будет переносить скрипты на другой сервер.

В итоге я расчехлил архивы трехлетней давности и все приложение свелось к последовательному вызову нескольких методов:

my $feeds_ref = FeedCrawl::Register::getFeeds();

foreach my $feed (@$feeds_ref) {
    print $feed->id . ' ' . $feed->uri . "\n";
    $feed->fetch();
    $feed->save();
}

Признак старинной архивной копии — вызов print 🙂

Ну а пост в Твиттер — тривиальная операция. Все сразу заработало, а через несколько часов окончательно вышел из строя жесткий диск на арендованном у «Мастерхоста» сервере, поэтому скрипт переехал жить и работать во Франкфурт.

Far East Perl 2008 — что было до и после

Про Дальневосточный Perl-воркшоп, который прошел год назад во Владивостоке, тоже есть что рассказать помимо собственно перла.

Уже то, что мероприятие прошло на другом конце континента, докуда от Москвы лететь восемь часов (а обратно — девять), само по себе волнующе. Это была моя первая вылазка на Дальний Восток.

Зарегистрировалось около 30 человек, в основном, разумеется, из Владивостока. Приехал и Джонатан Вортингтон. К сожалению, никого не было ни из Хабаровска, ни из Японии (хотя, впрочем, из Японии во Владивосток добраться сложнее, чем из Москвы).

Экскурсионная программа (за которую спасибо Vladivostok.pm — ДимеИлье и Роману) для организаторов и гостей включала, не считая прогулок по городу и чаепитий, поездку к Русскому острову и шашлыки на природе с исследованием подземных ходов.

Русский остров — особый пункт для тех, кто любит Гришковца.

Не менее интересно было спуститься в заброшенные ходы владивостокских фортов.

Видеозаписи всех выступлений на Дальневосточном Perl-воркшопе доступны на yapc.tv.

Perl и Project Euler

Часть задач, опубликованных на сайте Project Euler, удобно решать с помощью перла.

Некоторые задачи — исключительно математические, а некоторые требуют посимвольной обработки чисел или строк.

Например, задача на поиск чисел-палиндромов, то есть чисел вида 78987. С одной стороны, они представимы в виде суммы 7·104 + 8·103 + 9·102 + 8·101 + 7·100, но с другой — это последовательность символов, которые легко преобразовать в массив односимвольных элементов:

my @digits = split //, $number;

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

$product *= $_ for split //, substr $n, $c, 5;

Кроме того, некоторые задачи подразумевают большие числа — настолько большие, что размера стандартных переменных (например, long long в C++) недостаточно для их представления. Для работы с такими числами в перле удобно воспользоваться модулем Math::BigInt или прагмой bigint, после чего программа, вычисляющая сумму цифр факториала ста, становится тривиальной:

$i = $i->bmul($_) for 2..100;
. . .
$s += $_ for split //, $i;

Итальянский Perl-воркшоп

22 и 23 октября в Пизе пройдет пятый итальянский Perl-воркшоп.

Итальянский воркшоп (как и недавний Nordic Perl Workshop в Осло) собрал участников не только из Италии. В списке числятся 13 стран: Италия, Великобритания, Германия, Ирландия, Испания, Норвегия, Россия, Голландия, Иран(!), Бельния, США, Австрия, Словакия.

Изменения в работе given/when в Perl 5.10.1 (часть 2)

Второе изменение в работе when — возможность использования оператора //.

Оператор defined-or (//), появившийся в Perl 5.10, теперь может быть использован и как булево выражение в операторе when.

Работает он так, как интуитивно и ожидается:

use v5.10.1;

my $approx1 = undef;
my $approx2 = 3;
my $approx3 = 3.14;

given (3) {
    when($approx1 // $approx2) {say '1 or 2'}
    when($approx2 // $approx3) {say '2 or 3'}
    default {say 'None'}
}

В этом примере сработает первое условие.

Наиболее очевидное применение оператора // — подстановка значения по умолчанию. В следующем примере показана функция, которая ищет либо явно указанное число, либо 123 по умолчанию:

use v5.10.1;

my @data = <DATA>;

find(\@data);
find(\@data, 456);

sub find {
    my $a_ref = shift;
    my $value = shift;   

    say "find called";

    for (@$a_ref) {
        when ($value // 123) {say "Number $_"}
        when (/^\w+$/) {say "String $_"}
    }
}

__DATA__
alpha
123
beta
456
gamma
7.89

Поиск адекватных примеры из реальных приложений, в которых применяются новшества, по-видимому потребует не один месяц ожидания 🙂

Изменения в работе given/when в Perl 5.10.1 (часть 1)

В недавно вышедшем релизе Perl 5.10.1 слегка изменилась работа оператора when.

В частности, оператор when теперь понимает конструкцию «флип-флоп».

«Флип-флоп» — это оператор диапазона .. в булевом контексте. В документации приводится пример выражения для поиска POD-комментариев:

when (/^=begin/ .. /^=end/) {
   # do something
}

Аналогично возможно, например, находить определение функций во многих языках программирования, в частности, PIR:

use v5.10.1;

my $lineno = 0;
for (<DATA>) {
    chomp;
    print 'Line ', ++$lineno, ': ';
    when (/^\.HLL/) {say "switching language to $_"}
    when (/^\.sub/ .. /^\.end/) {say "subroutine body: $_"}
}

__DATA__
.HLL unknown
.sub main :main
    say "Demonstrating inc"
    $I = 2
    inc $I
    say $I
.end

Эта программа напечатает комментарии к каждой строке кода, объясняя его назначение:

Line 1: switching language to .HLL unknown
Line 2: subroutine body: .sub main :main
Line 3: subroutine body:     say "Demonstrating inc"
Line 4: subroutine body:     $I = 2
Line 5: subroutine body:     inc $I
Line 6: subroutine body:     say $I
Line 7: subroutine body: .end

Cледует обратить внимание на два момента. Во-первых, выражение, переданное when, срабатывает на всех строках подпрограммы, включая первую и последнюю, заданные границами /\^.sub/ и /\^.end/.

Во-вторых, оператор ведет себя «нежадно», что позволяет находить непересекающиеся последовательности. Вот программа, в которую дописана дополнительная подпрограмма на PIR, и строка when, находящая пустую строку:

use v5.10.1;

my $lineno = 0;
for (<DATA>) {
    chomp;
    print 'Line ', ++$lineno, ': ';
    when (/^\.HLL/) {say "switching language to $_"}
    when (/^\.sub/ .. /^\.end/) {say "subroutine body: $_"}
    when (/^$/) {say "empty line"}
}

__DATA__
.HLL unknown
.sub main :main
    say "Demonstrating inc"
    $I = 2
    inc $I
    say $I
.end

.sub another
    say 'Hey, you!'
.end

Вывод программы подтверждает правильность ее работы:

Line 1: switching language to .HLL unknown
Line 2: subroutine body: .sub main :main
Line 3: subroutine body:     say "Demonstrating inc"
Line 4: subroutine body:     $I = 2
Line 5: subroutine body:     inc $I
Line 6: subroutine body:     say $I
Line 7: subroutine body: .end
Line 8: empty line
Line 9: subroutine body: .sub another
Line 10: subroutine body:     say 'Hey, you!'
Line 11: subroutine body: .end

Другой пример использования — поиск и сохранение фрагмента алфавитно отсортированного списке, как это делают в бумажных словарях по двум-трем начальным буквам.

use v5.10.1;

my @programming_languages = qw(
    Pascal Pawn PCASTL PCF PEARL Perl PHP Phrogram Pico Pict Piet Pike PIKT PILOT Pizza PL/0 PL/B PL/C PL/I PL/M PL/P PL/SQL PL360 PLANC Plankalkül PLEX PLEXIL Pliant POP-11 Poplog PostScript PortablE Powerhouse PPL Processing Prograph PROIV Prolog Promela PROTEL Proteus ProvideX Pure Python
);

for (@programming_languages) {
    when (/^pa/i .. /^pi/i) {push @page, $_}
}
pop @page;
say join ', ', @page;

Программа подготовит данные для страницы словаря PA—PI:

Pascal, Pawn, PCASTL, PCF, PEARL, Perl, PHP, Phrogram

Разумеется, в последнем примере возможно было воспользоваться одним регулярным выражением:

my @page = ();
for (@programming_languages) {
    when (/^p[a-h]/i) {push @page, $_}
}

say join ', ', @page;

Но первый вариант в данном случае более нагляден и, к тому же, более расширяем. Напрмер, метод возможно вынести в отдельную функцию и передавать ей границы диапазона в виде параметров:

say join ', ', select_range('pa', 'pi');

sub select_range {
    my ($from, $to) = @_;

    my @page = ();
    for (@programming_languages) {
        when (/^$from/i .. /^$to/i) {push @page, $_}
    }
    pop @page;
   
    return @page;
}

TinyURL::RU

Мой коллега подготовил и опубликовал модуль TinyURL::RU для работы с сайтом byst.ro (он же — tinyurl.ru).

Интерфейс модуля предельно прост и содержит две функции: shorten для сокращения адреса и lenghen для обратного преобразования:

use TinyURL::RU qw(shorten lengthen);

say shorten("http://ironman.enlightenedperl.org/");
say lengthen("77d");

Наш tinyurl.ru выгодно отличается от других подобных сервисов тем, что дает возможность самостоятельно выбрать, как будет выглядеть короткий адрес: а именно, попробовать запросить и часть адреса после слеша, и даже поддомен третьего уровня:

my $tower = shorten("http://maps.google.com/maps. . .", "pisa", "tower");

Этот пример создаст адрес pisa.byst.ro/tower (если он, конечно, был доступен на момент запроса).

Модуль содержит плагин WWW::Shorten::TinyURL::RU, который может работать вместе с WWW::Shorten Дейва Кросса.