Архив Март 2010

См. также Новое в Perl 5.12 — часть I

each для массивов

Встроенная функция each работает с массивами. Она возвращает пары значений «индекс — значение», каждый раз сдвигаясь по массиву на единицу:

use v5.12;

my @a = 1..10;
while (my ($a, $b) = each @a) {
    say "$a, $b";
}

Эта программа печатает следующее:

0, 1
1, 2
2, 3
3, 4
4, 5
5, 6
6, 7
7, 8
8, 9
9, 10

Постфиксная форма when

when теперь выглядит еще более независимым от given. В Perl 5.12 возможно использовать when в качестве модификаторов инструкций, как это разрешено для if и unless.

use v5.10;

for ('a'..'z', 'A'..'Z') {
    say when /[aeiou]/i;
}

Локальный delete local для хешей

Комбинация ключевых слов delete local позволяет локально удалить элемент из хеша. После выхода из соответствующей области видимости хеш остается прежним.

use v5.12;

my %h = (
    alpha => 'a',
    beta => 'b',
    gamma => 'g',
);

say for keys %h; say; # gamma beta alpha

{
    delete local $h{beta};
    say for keys %h; say; # gamma alpha
}

say for keys %h; say; # gamma beta alpha

Кроме того

  • Perl 5.12 включает обновленные таблицы юникода.
  • В функциях работы со временем решена проблема 2038 года.
  • Разрешена перегрузка оператора qr.
  • Находясь внутри when, // ведет себя как || (э-м-м, требует осмысления).

Наконец, есть некоторые изменения в работе смартматчинга (в том числе, и в given/when), которые появились еще в Perl 5.10.1 (часть 1, часть 2).

21 марта на CPAN появился релиз-кандидат Perl 5.12. 29 марта — RC1. Еще через неделю пора ставить 5.12 в продакшн :-)

strict по умолчанию

Явное указание use v5.12 неявно делает активным strict.

Например, программа

use v5.10;
say $x;

отработает без ошибок, а похожая, но с явно упомянутой версией 5.12 (если быть точным, то более 5.11), уже не скомпилируется:

use v5.12;
say $x;

Global symbol "$x" requires explicit package name at 2.pl line 3.
Execution of 2.pl aborted due to compilation errors.

Версии модулей

В Perl 5.12 возможно указывать версию модуля одновременно с его именем, избавляясь от переменной $VERSION:

package Earth::Gravity 9.8;

sub g {
    return 9.8;
}

1;

Аналогичный синтаксис в директиве use работает по-прежнему, позволяя указывать минимально необходимую версию:

use v5.12;
use Earth::Gravity 9.8;

say g();

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

Например, если в каталоге lib лежит модуль Earth::Gravity 9.81, то успех будет зависеть от порядка просмотра каталогов:

$ perl5.12.0 -I. -Ilib test.pl
Earth::Gravity version 9.81 required--this is only version 9.8 at 2.pl line 3.
BEGIN failed--compilation aborted at 2.pl line 3.

$ perl5.12.0 -Ilib -I. test.pl 9.81

Номер версии по-прежнему доступен через переменную $VERSION, даже если она не была инициализирована явно:

$ perl5.12.0 -mEarth::Gravity -E'say $Earth::Gravity::VERSION' 9.8

Оператор Yada Yada (...)

(Еще один вопрос для собеседования :-)

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

При попытке выполнить код, содержащий Yada Yada, возникнет ошибка (времени исполнения):

use v5.12;

sub calculate_salary {
    ...;
}

say 'before';
calculate_salary;
say 'after';

$ perl5.12.0 test.pl
before
Unimplemented at test.pl line 4.

Yada Yada правильно распознается только в том случае, если использовано в конструкции, подразумевающим законченное выражение. В остальных случаях ... может быть распознан как один из вариантов оператора диапазона.

Правильное использование:

sub calculate_salary {
    ...;
}

Неправильное использование (вызовет ошибку при компилировании):

say base_salary + ...;

Метасимвол \N в регулярных выражениях

Метасимвол \N совпадает со всеми символами, кроме перевода строки \n, причем независимо от наличия модификатора /s.

use v5.12;

"abc\ndef" ~~ /(\N+)/;
say $1; # abc

"abc\ndef" ~~ /(\N+)/s;
say $1; # abc

В этом значении метосимвол является экспериментальным; в частности, из-за возможных конфликтов в использовании с именованными символами, которые прагма charnames делает доступными с помощью очень похожиго синтаксиса: \N{GREEK SMALL LETTER PI}, в то время как повторы нескольких символов \N может быть записан с помощью стандартного квантификатора: \N{5}.

См. также Новое в Perl 5.12 — Часть II

5.12.0 RC1

| Нет комментариев

На спане появился Perl 5.12.0 RC 1: search.cpan.org/~jesse/perl-5.12.0-RC1. Йоу.

CPAN vs. GitHub

| Комментариев: 3

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

Приводятся ссылки на четыре модуля, и все они лежат на гитхабе. А модули-то интересные, например, HTML::Image::Size.

Сформулирую мысль кратко и в тезисах.

  • Github дает удобные инструменты для работы над кодом, но поди догайся, что нужно искать модуль именно там.
  • CPAN позволяет более или менее удобно искать, но, разумеется, спан не заглядывает на гитхаб. И самое плохое, что процесс регистрации на нынешнем PAUSE весьма не дружелюбный.
  • Две точки входа размывают единое пространство имен, что когда-нибудь может привести к появлению двух разных, но одинаково названных модулей.

for vs. given

| 1 комментарий

Иногда вместо given удобно использовать for, например, чтобы сделать несколько проверок для каждого элемента массива.

Однако, эта легкость замены дает ложное ощущение возможности и обратного — использования given вместо for.

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

Например:

for ($url) {
    s{\.?*}{};
    s{^/}{};
    s{/$}{};
}

Фактически никакого цикла здесь нет, и уж если подключен use 5.10, хочется использовать given. Однако, не тут-то было. Хотя given и создаст переменную $_, но она будет всего лишь лексической переменной в пределах блока given, а не синонимом $url.

use v5.10;
use strict;

my $string = 'Hello, Perl';
my $another = $string;

for ($string) {
    s/Hello/Hallo/;
    s/Perl/C++/;

}

given ($another) {
    s/Hello/Hi/;
    s/Perl/JavaScript/;

}

say $string;  # Hallo, C++
say $another; # Hello, Perl

Этот пример выведет измененную строку после блока с for и неизменную — после given. Будьте внимательны :-)

Автор ясень, автоматически переводятся с английского языка.

Краткая версия: SayPerl.org сайт запущен. Она обеспечивает Английский перевод для Perl сообщения со всего мира.

Длинная версия:

Железный Человек и PlanetPerl.ru показали, что Есть много людей Perl, которые пишут о Perl и вы никогда не слышали о них.

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

Копирование-вставка после URL-адреса в Google Translate на ежедневной основе очень раздражает. Я поймал себя на начало чтения последних итальянских сообщения о предстоящих YAPC:: Европе, а затем переход к Google Translate, как я не могу много читать итальянский еще. То же самое с немецким. Оба они являются более понятными, чем японские, хотя :-)

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

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

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

Чтобы продемонстрировать преимущества SayPerl.org, сравнивать эти две должности, оригинальных и переводных:

Слово "Rakvdv", который выглядит так, как это будет написано древние римляне, четко понятно сейчас.

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

Что касается технических деталей, я только хотел бы отметить еще одну проблему с обработкой Unicode. Так произошло и с WebService:: Google:: Язык. Такие ошибки являются одним из наиболее распространенных проблем с модулями Perl сегодня (вспомните, например, еще одна проблема с Unicode возникает тогда, когда Алекс кодирования PlanetPerl.ru).

sayperl.org

Начало использования SayPerl.org прямо сейчас!

Я не могу сказать, что читаю все, что пишут на Iron Man, как впрочем и на Planetperl.ru. А вот сегодня подряд собралось несколько интересных постов, которые хочется упомянуть и здесь. Четыре подряд идущих поста затрагивают четыре важных стороны Perl-сообщества: Perl-блоги, модные библиотеки, неотрицание других языков и конференции.

Caleb Cushing. Perl Blogger annoyances.
Краткое содержание: На «Айронмене» нет разделения по языкам. Даже спецпоток, состоящий только из английских записей автора заметки не устраивает, поскольку там сбивается форматирование. Часто хз, как написать комментарий. Примерно каждое двадцатое сообщение — «спам», потому что без контента.

Stevan Little. Moose 1.0 is released.
В общем, заголовок исчерпывающ :-) Переход от версии 0.99 к единичной всегда событие и для авторов, и для пользователей. Хотя я все равно не люблю Moose.

Michael Peters. Perl hashes in comparison to C, C++, Python and Ruby.
Ссылочка на сравнение различных реализаций хешей.

Michele Beltrame. YAPC::Europe 2010: non solo conferenza («YAPC:Europe 2010 — не только конференция»).
Небольшой обзор того, какие события обычно происходят на конференциях YAPC::Europe: учебные курсы (и до, и после основных дней мероприятия), хакатоны и так называемые BOF (вечерние группы по интересам), питье и еда, экскурсии для тех, кто едет за компанию, но не посещает YAPC.

На конференцию РИТ++ приезжает Джонатан Вортингтон. Джонатан уже был в России пару раз, однако впервые приезжает в Москву с докладом. За последние три года он посещал наши мероприятия в Киеве и Владивостоке.

Джонатан Вортингтон / Jonathan Wortingthon Джонатан Вортингтон (Jonathan Worthington) — британский программист, в течение нескольких лет участвующий в разработке виртуальной машины Parrot, а затем компилятора Perl 6 Rakudo. Джонатан приедет к нам вместо Патрика Мишо, который, к сожалению, не сможет выступить на РИТ++.

В настоящее время Джонатан является одним из ведущих разработчиков Rakudo и выступает с докладами про синтаксис Perl 6, внутреннее устройство компилятора и планах по его развитию. Презентации выступлений доступны на странице jnthn.net/articles.shtml.

Джонатан заядлый посетитель Perl-мероприятий по всему миру и совмещает участие в мероприятиях с путешествиями. В 2008 году, приехав на дальневосточный Perl-воркшоп, совершил железнодорожное путешествие от Владивостока до Минска.

В этом году с апреля по май раз в месяц будут проходить мероприятия, посвященные перлу.

Perl-поток «MayPerl» на конференции РИТ++. Москва, 12–14 апреля.

Perl-поток DevConf::Perl() на конференции DevConf. Москва, 17–18 мая.

Совместная конференция Perl Mova + YAPC::Russia. Киев, 12–14 июня.

Регистрация везде открыта. Везде требуются интересные докладчики. Perl Mova + YAPC::Russia, к тому же, бесплатна.

В серверном коде, обслуживащем сайт, блоки given/when весьма удобны в частности для того, чтобы последовательно протестировать URL запрошенного ресурса и выполнить соответствующие действия:

given($url) {
    when(m{^/$}) {home_page()}
    when(m{^/about/$} {about_page()}
    . . .
}

В Perl 5.10 помимо операторов given/when доступны именованные сохраняющие скобки, которые могут облегчить выделение параметров из адреса одновременно с его разбором:

given($url) {
    . . .
    when(m{^/news/(?<year>\d+)/(?<month>\d+)/(?<day>)/$})
        {news_that_day()}
}

Параметры, захваченные именованными скобками, попадают в хеши %+ и %-, которые следует передать дальше на обработку.

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

given($url) {
    . . .
}
say Dumper(\%+); #
Пусто

В этом месте кода переменные %+ и %- сохраняют значения, полученные до начала блока given.

Вплоне логично, хорошо локализовано, но не всегда удобно.

Разумеется, возможно сохранить собранные данные непосредственно в блоке given, хотя при легкомысленном проектировании это легко приводит к большим фрагментам повторяющегося кода:

given($url) {
    . . .
    when(m{^/(?<type>this)_page/$})
        {%data = %+; do_this()}
    when(m{^/(?<type>that)_page/$})
        {%data = %+; do_that()}
}

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

use v5.10;
use strict;

my $string = "Fri Mar 19 13:59:06 MSK 2010";
$string =~ /(?<tz>([A-Z]{3}))/;
say $+{tz};
say $1;
say $2;

Программа трижды напечатает MSK.

Итого, ответ на вопроса простой: учитываются все скобки.

Одна из задач, где Gearman позволяет получить удобство и скорость работы, — обработка текстовых поисковых запросов. Детально я хочу рассказать об этом на YAPC::Europe, а в этом посте покажу несколько фрагментов кода, который сейчас работает в продакшне.

Полученный поисковый запрос раздается на несколько сканеров, каждый из которых отвечает за свою узкую область знаний, например, за географический поиск. В свою очедерь, каждый сканер может уточнять задачу с помощью одного или нескольких парсеров, которые непосредственно и анализируют текст запроса. С точки зрения job-сервера, все это оформлено в несколько воркеров; всего их около двух десятков:

misc::e — поиск по кодам пищевых добавок,
misc::typo — проверка орфографии;

place::airport — поиск аэропортов,
place::country — поиск стран,
place::locality — поиск населенных пунктов;

whl::money — конвертер валют;

whl::area, whl::volume, whl::temperature, whl::speed, whl::pressure, whl::power, whl::mass, whl::length, whl::information, whl::force, whl::energy, whl::calendar — конвертеры единиц измерения;

whl::calculator — калькулятор.

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

Интересно, что каждая отдельная часть реализации довольно проста и уныла, примерно тот же эффект наблюдается, когда из бесконечных однострочных методов на Java выстраивается нетривиальное приложение, или как в ассемблере, где количество атомарных действий mov в итоге превращается в качество.

Сканеры подгружаются автоматически при старте. О том, как это делается, недавно упоминалось в рассылке Moscow.pm. Расстановка тасков — перебор по списку:

my $tasks = $client->new_task_set;
for(@{$self->{scanners}}) {
    $tasks->add_task(
        $_ => nfreeze([$query, $self->{locale}]),
        {
            on_complete => sub {
                push @{$self->{results}}, thaw(${$_[0]});
            },
        },
    );
}
$tasks->wait;

Типовой сканер содержит метод, принимающий строку запроса. В частности, сканер единиц измерения и валют раздает задачи своим парсерам:

sub scan {
    my $query = shift @args;

    for my $parser (@{$self->{parsers}}) {
        my $result =
           $parser->parse($query, $self->{locale}) // next;
        push @{$self->{results}}, $result;
    }
}

(Обатите внимание, кстати, на использование оператора defined-or для завершения итерации цикла.)

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

Разумеется, в большинстве случаев ответ находят лишь некоторые из двух десятков воркеров. Более того, часть ответов игнорируется на уровне XSLT в зависимости от того, насколько полными были ответы от тех или иных воркеров.

Вот пример запроса: sin(pi/2) + cos(pi/2). Нефильтрованные данные, полученные от всех сканеров, выглядят следующим образом:

Те же данные с точки зрения XML-наблюдателя:

<pack for="sin(pi/2) + cos(pi/2)" scanner="whl::calculator">
    <item>
        <from expr="sin(π/2) + cos(π/2)"/>
        <to value="1"/>
    </item>
</pack>
<pack for="sin" scanner="place::locality">
    <item country-code="FR" geonameid="2974494">Sin-le-Noble</item>
    <item country-code="AF" geonameid="1124363">Sīn</item>
    . . .
</pack>
<pack for="pi" scanner="place::locality">
    <item country-code="FR" geonameid="2984891">Py</item>
    <item country-code="ES" geonameid="6424319">Pi</item>
    <item country-code="IN" geonameid="1259715">Pi</item>
</pack>
<pack for="cos" scanner="place::locality">
    <item country-code="FR" geonameid="3023491">Cos</item>
    <item country-code="ES" geonameid="3124419">Cos</item>
    . . .
</pack>

Парсер калькулятора вернул один результат (собственно, наиболее релевантный), а географический сканнер нашел города с названиями и Синус, и Косинус, и Пи — эти результаты при наличии первого результата, который поглотил всю строку, показывать, разумеется, не обязательно. Большинство возможностей, которые сегодня умеет делать упоминаемый здесь поиск, описаны на соответствующей странице.

when со скаляром

Простейший вариант использования конструкции с ключевым словом when — указание констант в условиях проверки.

foreach (@hazards) {
    when ($WUMPUS) {
        $self -> lose;
        push @messages => "Oops! Bumped into a Wumpus!";
    }
    when ($PIT) {
        $self -> lose;
        push @messages => "YYYIIIIEEEE! Fell in a pit!";
    }
    when ($BAT) {
        push @messages => 

           "ZAP! Super bat snatch! Elsewhereville for you!";
    }
}

Games::Wumpus — 24 Nov 2009
Play Hunt the Wumpus

Забегая вперед, обратите внимение на то, что when не обязательно использовать исключительно внутри блока given. Любой вызов when выполняет сопоставление с переменной $_, поэтому они хорошо работают в конструкциях for и foreach, которые используют ее в качестве переменной по умолчанию на текущей итерации.

when для выбора вариантов

Выбор одного из нескольких вариантов — самое очевидное применениее конструкции given/when.

given ($k) {
    when ('file')    { $opt_file     = $v; }
    when ('argv')    { $opt_argv     = $v; }
    when ('inter')   { $opt_interact = $v; }
    when ('prompt')  { $opt_prompt   = $v; }
    when ('quiet')   { $opt_quiet    = $v; }
    when ('tty_in')  { $tty_in       = $v; }
    when ('tty_out') { $tty_out      = $v; }
    default {
        die "Error: in subroutine set_opt(), 
             found invalid key {$k => '$v'}
             (not 'file', 'argv', 'inter', 'prompt',
             'quiet',
 'tty_in' or 'tty_out')";
    }
}

Term::DBPrompt — 18 Dec 2009
Commandline prompt for a database application

given ($inp_typ)
    when ('f') . . .
    when ('a') . . .
    when ('i') . . .
    default {
        die "Internal error: type = 
             '$inp_typ' (not 'f', 'a' or 'i')";
    }
}

Term::DBPrompt — 18 Dec 2009
Commandline prompt for a database application

when с булевым выражением

Следующая «ступень» — использовать внутри when не константы, а выражения с переменной $_, в частности, булевые:

unless ( 'itan' ~~ @list ) {
    given ( length $password ) {
        when ( 16 ) {
            # ok
        }
        when ( $_ < 4 ) {
            die('ERROR: Password is too short 
                (Min 4 bytes required)');
        }
        when ( $_ > 16 ) {
            die('ERROR: Password is too long 
                (Max 16 bytes allowed)');
        }
        default {
            while (1) {
                $password .= '0';
                last 
                    if length $password == 16;
            }
        }
    }

App::iTan::Utils — 26 Oct 2009
Secure management of iTans for online banking

Кстати, в этом примере конструкция выбора обрамлена условием с использованием смартматчинга:

unless ( 'itan' ~~ @list )

when с регулярным выражением

Сделать проверку с использованием регуляного выражения так же просто, как и с константой.

sub range2list {
    my $_ = shift;
    given ($_) {
        when (/^(\d)\-(\d)$/o )   { return "$1..$2" }
        when (/^\d\.\.\d$/o )     { return "$_" }
        when (/^\d$/o )           { return $_}
        when (/^(.*?),(.*)$/o )   { return range2list($1). ','
                                          .range2list($2)}
        default                   { return ''}
    }
}

Catalyst::Devel

when и ref

Помимо проверки значения возможно проверять и тип переменной:

given(ref $fdef){
    when('ARRAY'){

Package::FromData — 14 Jan 2008
generate a package with methods and variables from a data structure

when и undef

Не столь очевидно, однако вполне законно, сопоставление с undef. В этом случае блок when принимает управление, если переменная неопределена.

given ($1) {
    when (undef)  {return}
    when ($left)  { $depth++; }
    when ($right) { $depth--; }
}

Parse::Marpa::Lex

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

given ($action) {
    when (undef) {;}    # do nothing
                        # Right now do nothing 
                        # but find lex_q_quote
    when ('lex_q_quote') {
        $lexers[$ix] =
            [ \&Parse::Marpa::Lex::lex_q_quote,
               $prefix, $suffix ];
    }

Parse::Marpa::Recognizer

Вложенные блоки given/when

Блоки given/when легко объединяются и образуют вложенные конструкции.

given($name) {
    when ('stream:stream') . . .
    when ('challenge') . . .
    when ('failure') . . .
    when ('stream:features') . . . 
        given(my $clist = $node->getChildrenHash()) {
            when ('starttls') . . .
            when('mechanisms') . . .
                foreach($clist->{'mechanisms'}->

                  [0]->getChildrenByTagName('*'))
                    when($_->textContent() eq 'DIGEST-MD5' 
                      or $_->textContent() eq 'PLAIN')
            when('bind') . . .
            default . . .
    when ('proceed') . . .
    when ('success') . . .

POE::Component::Jabber — 22 Mar 2009
A POE Component for communicating over Jabber

Стоит отметить, что вложенные конструкции в некоторых случаях возможно развернуть в одноуровневые.

for и when

Несмотря на то, что ключевое слово when появилось в Perl 5.10 одновременно с given и default, ничто не обязывает всегда использовать их совместно. Как уже упоминалось, действие, выполняемое функцией when, во многих случах явлется сопоставлением переменной по умолчания $_ с указанным значением (константой, регулярным выражением, списком и т. д.). Поэтому иногда when удобно применять вместо последовательности if/elsif/else.

for ( catch ) {
  when ( $_->isa('Getopt::Lucid::Exception::ARGV') ) {
    say;
    # usage stuff
    return 1;
  }
  default { die $_ }
}

App::CPAN::Mini::Visit — 07 Nov 2008
explore each distribution in a minicpan repository

Cмартматчинг (~~)

Оператор сопоставления используется довольно часто, хотя и менее популярен, чем оператор //.

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

return _fail( $pkg, $sub ) if $_ ~~ 0;

if ( $attr ~~ /^Export_?Lexical$/i ) {

Export::Lexical — 09 Oct 2008
Lexically scoped subroutine imports

Интересен пример использования оператора ~~ внутри блока кода встроенной функции grep.

@exportz = grep { ! ( $_ ~~ @argz ) } @_;

$disp ~~ @exportz or push @exportz, $disp;

Exporter::Proxy — 29 Jan 2010
Simplified symbol export & proxy dispatch

В этом же фрагменте есть еще не менее интересное и практичное применение: ~~ удобно привлекать, чтобы определить, содержится ли элемент с неким значением в списке.

Чуть более нагляден вариант, в котором условие записано в постфиксной форме:

push @exportz, $disp unless $disp ~~ @exportz;

Смартматчинг, выполненный внутри if, разумеется, возможен, однако в таких случаях стоит задумться об использовании when, поскольку он неявно использует именно смартматчинг.

for( @_ )
    {
        index $_, ':'
        or next;

        if( $_ ~~ @exportz )
        {
            my $source  = qualify_to_ref $_, $source;
            my $install = qualify_to_ref $_, $caller;

            *$install   = *$source;
        }
        else
        {
            die "Bogus $source: '$_' not exported";
        }
    }

Exporter::Proxy — 29 Jan 2010
Simplified symbol export & proxy dispatch

Именованные сохраняющие скобки

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

my $compiled_regex = qr{
    \G
    (?<mArPa_prefix>$prefix)
    (?<mArPa_match>$regex)
    (?<mArPa_suffix>$suffix)
}xms;

Parse::Marpa::Recognizer


Продолжение будет.

После вечернего моциона по Тверскому бульвару мне пришла мысль о том, что ведь в C++ довольно просто создать функцию say(), которая будет работать и с числами, и со строками :-)

#include<iostream>

template<typename T> void say(T value) {
    std::cout << value << "\n";
}

int main() {
    say(42);
    say(3.14);
    say("Perl");
    
    return 0;
}

Perl на DevConf

| Нет комментариев

DevConfОткрыт сайт конференции DevConf 2010 года. Конференция пройдет в Москве 17–18 мая.

В этом году на DevConf отдельным потоком пройдет «вложенное» мероприятие — конференция DevConf::Perl().

Одновременно объявляется прием заявок на выступления на доклады про любые аспекты современного программирования на Perl:

  • Carl Mäsakв промышленных масштабах;
  • в быту;
  • в системном администрировании;
  • на вебе;
  • совместно с другими языками;
  • в команде;
  • в одиночном плавании.

В конференции примет участие Карл Мэсак — программист из Швеции, активно участвующий в разработке компилятора Perl 6 Rakudo. Именно этой весной планируется выпустить первый релиз. Карл является лидером по числу баг-репортов в рассылке perl6-compiler. В 2007 году на конференции YAPC::Europe он презентовал написанный со своим товарищем November — вики-сайт на Perl 6.

Регистрация, оплата и личный кабинет находятся на общем сайте конференции DevConf. Присоединяйтесь (=заставьте своего работодателя вложиться в Perl)!

Вчера я упоминал о баге в Padre, связанном с не-ASCII-символами. Строка

say "Превед!";

превращалась при сохранении файла в

say "\x{041f}\x{0440}\x{0435}\x{0432}\x{0435}\x{0434}!";

После сообщения об ошибке в траке баг был исправлен через несколько минут. Весьма смешным образом, методом исключения лишнего кода :-)

return 'ascii' unless $content =~ /[^[:print:]\015\012]/;
#return 'ascii' unless $content =~ /[^[:print:]\015\012]/;

say say say

| Комментариев: 3

Фрагмент из тестового файла, который мне потребовался, чтобы проверить работу части проекта, написанного на C++:

void say(double value) {
    std::cout << value << "\n";
}

int main() {
    say(calc("1+2"));

    return 0;
}

Strawberry Perl Professional

| 1 комментарий

Strawberry Perl — максимально совместимая Windows-версия Perl — скоро будет доступна в двух вариантах: в обычном и Pro. Сейчас Strawberry Perl Pro 5.10.1.1 Alpha 1 возможно загрузить по адресу strawberryperl.com/beta.

В комплекте Pro-версии добавлены модули для работы с криптографией (которые утомительно собирать вручную), BioPerl (почему и зачем?), Catalyst и — на мой взгляд самое важное — собранный Padre.

После установки в соответствующей папке Program Files помимо собственно исполнимых файлов и оболочек Perl и CPAN появляются ссылки на документацию, а также на пару инструментов, которые еще не работают.

Strawberry Perl

Strawberry Perl

P. S. Padre хоть и не падает при запуске, по-прежнему но непригоден для задач, которые я смог бы в нем решать. Например, строка кода say "Превед!" после сохранения превращается в say "\x{041f}\x{0440}\x{0435}\x{0432}\x{0435}\x{0434}!" (исправлено).

Часть III
Как пишут другие

В этом разделе собраны и сгруппированы примеры использования новых возможностей Perl 5.10, которые встречаются в модулях на CPAN.

Как включить режим Perl 5.10

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

Cпособы, которыми пользуются авторы, как нельзя лучше демоснтрируют принцип TIMTOWTDI:

use 5.010000;
use 5.01001;
use 5.010;
use 5.010_000;
use 5.10.0;
use v5.10.0;
use v5.10;
use feature ':5.10';

Строки, начинающиеся с буквы v, либо содержащие две точки, называются v-string (version string или, иногда, vector string). При объявлении версии интерпретатора следущие варианты эквивалентны.

5.10.0
v5.10.0
v5.10

Обратите внимание, если при указании версии используется обычное число (с одной десятичной точкой), то следует писать не 5.10, а 5.010.

say для отладки

Функцию say удобно использовать во время отладки программы для вывода промежуточных значений переменных. На CPAN можно найти следы такой отладки — закомментированный вызов say.

given ($action) {
    when (/^include_cmd:/) {
        my $cmd = $child->content;
        $cmd =~ /^include_cmd:(\s*)/;
        my $ws = $1 || '';
        $cmd =~ s/^include_cmd:\s*//;
        #say("cmd:$ws$cmd");
        $cmd = cwd() . '/' . $cmd;
        @output = qx($cmd);
        $child->content($ws . join($ws, @output));
    }

Pod::Elemental::Transformer::Include — 08 Jan 2010
include output via files and commands

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

// и //= для значений по умолчанию

Пожалуй, самое распространенное применение оператора defined-or — установка значений по умолчанию.

В частности, удобно пользоваться вариантом с присвоением.

$port //=  5432;
$host //= 'localhost';

$col  //= '';

Pg::Loader — 07 Jul 2008
Perl extension for loading Postgres tables

$attrz{ maxjob  } //= 1;
$value //= 1;

$attrz{ $_ } //= 0;
$attrz{ verbose } //= '';
$attrz{ debug   } //= '';
$val //= 1;
$exit //= 0;
$skipz->{ $job_id } //= 'Skip on SIGHUP'

Parallel::Depend — 12 Aug 2009
Parallel-dependent dispatch of perl or shell code

Чуть более сложный пример — с обращением к встроенной функции:

sub import   {
    shift;
    my %args = @_;
    # we do not care about autoviv
    $^H{fixedtime} = $args{epoch_offset} // 
                     CORE::time;
}

fixedtime — 14 Aug 2008
lexical pragma to fix the epoch offset for time related functions

Defined-or используют и непосредственно при передаче аргументов функциям.

say $answer // 
    "I don't know enough to answer you yet.";

Hailo — 29 Jan 2010
A pluggable Markov engine analogous to MegaHAL

Следует обратить внимание, что оператор возможно использовать не только с истинными скалярами.

my $marpa_version  = 
$Parse::Marpa::VERSION // 'undef';
my $source_version = 
$Parse::Marpa::Source::VERSION // 'undef';

$options //= {};

Parse::Marpa — 14 Dec 2008
Generate Parsers from any BNF grammar

В следующем примере помимо многократного использования // интересно отметить, что say передается файловый дескриптор.

my $nulling_symbol =
  $rhs_symbol->[Parse::Marpa::Internal::Symbol::NULL_ALIAS] // $rhs_symbol;

$action //= $default_action;

say {$trace_fh}
    'Problems compiling action for original rule: ',
    Parse::Marpa::brief_original_rule($rule);

my $clone = $clone_arg // 1;
my $current_parse_set = $parse_set_arg // $default_parse_set;

$choice //= 0;

$lines //= [0];
$source_options //= {};

Parse::Marpa::Internal::Evaluator — 14 Dec 2008
Generate Parsers from any BNF grammar

Наконец, и сам файловый дескриптор удобно вписывается в работу с defined-or:

my $trace_fh = $arg_trace_fh // (*STDERR);

my $trace_fh = shift;
$trace_fh //= *STDERR;

Parse::Marpa::Recognizer — 14 Dec 2008
Generate Parsers from any BNF grammar

// внутри return

Оператор defined-or часто встречается внутри вызова return, опять же чтобы вернуть определенное значение, если оно не получено на предыдущих шагах.

return $self->_get_infection( $disease->id ) // 0;

my $val = $self->_get($key) // $default->{$key};


return @{ $self->_players // [] };

Games::Pandemic::City, Games::Pandemic::Config — 07 Sep 2009
Games::Risk — 18 Oct 2008

Иногда в одном из операндов // вызывают фукнции, которые могут привести к досрочному завершению программы или выходу из блока.

sub homedir {
  my ($self) = @_;
  require File::HomeDir;
  return File::HomeDir->my_home
    // croak 'File::HomeDir says you have no home
              directory';
}

App::RSS2Leafnode — 02 Feb 2010
post RSS feeds to newsgroups

А вот пример, когда операндом является целый блок кода do:

sub config_filename {
  my ($self) = @_;
  return $self->{'config_filename'} // do {
    require File::Spec;
    File::Spec->catfile ($self->homedir, '.rss2leafnode.conf');
  };
}

App::RSS2Leafnode — 02 Feb 2010
post RSS feeds to newsgroups

В частных случаях // действует лишь внутри части выражения, передаваемое return.

return 
isodate_to_rfc822($date // $self->{'now822'});

return URI::Title::title
    ({ url  => ($resp->request->uri // ''),
       data => $resp->decoded_content 
 (charset => 'none')});

App::RSS2Leafnode — 02 Feb 2010
post RSS feeds to newsgroups

return внутри //

Весьма распространена и противоположная конструкция, когда в одном из плеч // делают попытку возврата из подпрограммы.

my $b_time = $self->item_to_timet($b_item)
   // return $a_item;

my $a_time = $self->item_to_timet($a_item) 
   // return $b_item;;

my $str = $self->item_to_date($item) 
   // return;

App::RSS2Leafnode — 02 Feb 2010
post RSS feeds to newsgroups

// легко объединяется в цепочку, поэтому возможно написать конструкцию, которая делает несколько попыток присвоить defined-значение:

return (elt_to_email ($item->first_child('author'))
        // elt_to_email ($item   ->first_child('dc:creator'))
        // elt_to_email ($item   ->first_child('dc:contributor'))
        // non_empty ($item->first_child_text('wiki:username'))

        // elt_to_email ($channel->first_child('dc:creator'))
        // elt_to_email ($channel->first_child('author'))
        // elt_to_email ($channel->first_child('managingEditor'))
        // elt_to_email ($channel->first_child('webMaster'))

        // elt_to_email ($item   ->first_child('dc:publisher'))
        // elt_to_email ($channel->first_child('dc:publisher'))

        // non_empty ($channel->first_child_text('title'))

        # RFC822
        // 'nobody@'.$self->uri_to_host
       );

App::RSS2Leafnode — 02 Feb 2010
post RSS feeds to newsgroups

Возможен и подход, при котором возвращается одна-единственная переменная, которая перед этим проходит через несколько проверок с оператором defined-or:

sub item_to_language {
  my ($self, $item) = @_;
  my $content;
  my $ret = (elt_to_language($item)
             // elt_to_language($item->first_child('content')));
  for (;;) {
    $item = $item->parent // last;
    $ret //= elt_to_language($item);
  }
  $ret //= $self->{'resp'}->content_language;
  return $ret;
}

App::RSS2Leafnode — 02 Feb 2010
post RSS feeds to newsgroups

Несколько //

Объединение в цепочку нам уже встречалось, однако на нем следует задержать внимание еще раз.

my $captures    = $arg {captures}       // [];
my $comment     = escape $arg {comment} // $name // "";
my $upgrade     = $arg {utf8_upgrade}   // 1;
my $downgrade   = $arg {utf8_downgrade} // 1;
my $match       = $arg {match}          // 1;

Games::Wumpus — 24 Nov 2009
Play Hunt the Wumpus


Продолжение будет.

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

В статусе job-сервера такие задачи видны с «перекошенным» счетчиком:

new_feature 14 0 0

То есть запросы на выполнение этой задачи в очедери уже есть, но обслужить ее некому. Непрятность здесь может быть в том, что как только подключится воркер, весь этот пул запросов потечет сразу к нему, и при отладке это крайне неудобно. Перезагружать job-сервер, чтобы обнулить счетчики, тоже не лучший выход, поскольку придется перезапустить все воркеры.

Мариан Маринов, технический архитектор компании SiteGround, сегодня добавил в интерфейс команду rmfunc, которая позволяет удалить функцию из списка зарегистрированных.

Пользоваться новой командой крайне просто:

$ telnet localhost 4730
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
status
new_feature 14 0 0
.
rmfunc new_feature
OK
status
.

Запрос на удаление функции, для которой существует «живой» воркер, завершается с ошибкой ERR there are still connected workers.

P. S. Сейчас весь код находится в отдельной ветке.

Несмотря на то, что проектирование интерфейсов — задача, которую програмисты не всегда решают успешно, картинка на новом сайте YAPC::Europe 2010 — великолепна.

Тема конференции — The Renaissance of Perl, проходит она в Италии, и лук в стиле записок Леонардо Ди Каприо, — прекрасен.

YAPC::Europe 2010

Да, а на ютубе (британцы говорят ючуб, кстати) есть ролик про качества перла.

Да здравствует перл! Этот блог работает на перле, но писали его неизвестные мне люди Я тут зашел куда-то в админской части, и увидел массу комментариев, которые, оказывается, висят неодобренными. :-O 

Часть я пооткрывал, а часть (ай!) удалил. Перл + юзабилити часто так же несовместимо, как и многие другие продукты, созданный программистами.

И еще я забыл с собой зарядное устройство от телефона.

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

Только что вернулся в гостиницу с седьмого голландского Perl-воркшопа. Он проходил в хостеле Stayok в городе Арнеме.

Это город в ста километрах от Амстердама, в часе езды электричкой (и еще полчаса от вокзала, то есть почти что московские расстояния от спальных районов до центра :-)

Как всегда, я сразу обращаю внимание на посещаемость, и даже под вечер она была около 90 % — из 39 зарегистрированных посетителей я насчитал 35.

Часть выступлений была на голланском языке (он напоминает смесь немецкого и английского с примесью французской картавости), поэтому все остальные, которые на английском, сразу стали вдвое интереснее :-)

Особенно хорош был Мартин Берендз, сделавший обзор интерпретаторов и компиляторов Perl 6, существующих в марте 2010 года. Мартин упомянул неофициальное понятие bus number, которое равно числу ведущих разработчиков проекта.

Леон Тиммерманс подкинул еще одну лингвошутку — unintentional feature (имеется в виду баг).

Через какое-то время должны появиться видеозаписи (их делали местные организаторы).

А после обеда сначала пошел мокрый снег, а потом — к вечеру — дождь; электричку пришлось ждать полчаса; и я теперь весь промокшый, но довольный :-)

Часть I
История и статистика

Perl 5.10 увидел свет в 20 день рождения языка — 18 декабря 2007 года. Уже прошло более двух лет, и за это время успели появиться девелоперские версии 5.11.0, 5.11.1, 5.11.2, 5.11.3 и 5.11.4, и вот-вот появится версия 5.12, предназначенная для использования в реальных приложениях.

Perl 5.10 представил много нововведений, и сегодня интересно посмотреть, как часто они используются авторами модулей CPAN — модулей, появившихся после релиза 5.10, либо обновленных с того времени.

На CPAN сейчас хранится около 80 000 модулей в 20 000 дистрибутивах, список авторов содержит около 8000 имен. Как часто здесь используются фичи Perl 5.10?

Ответ: новые фичи встречаются в двух сотнях модулей, созданных сотней авторов.


Часть II
Фичи Perl 5.10

Кратко о том, что появилось в Perl 5.10.

— Встроенная функция say, которая работает аналогично print, но добавляет перевод строки.

— Оператор сопоставления (смартматчинга) ~~ сопоставляет свои аргументы согласно здравому смыслу (и, разумеется, четким правилам, описанным в документации). Например, в этих примерах аргументы имеют разный тип, но используется один и тот же оператор.

$a ~~ /\d/

$a ~~ @list

@list ~~ %hash

— Составной оператор выбора под условным названием switch. С помощью новых ключевых слов given, when и default возможно создать условную конструкцию, аналогичную switch/case в C и других языках. Важное отличие в том, что внутри given происходит не простое сравнение, а сопоставление (или смартматчинг).

given($x) {
    when(/a/) {...}
    when('b') {...}
    default   {...}
}

— Модификатор state позволяет создавать лексические переменные, сохраняющие значение между вызовами подпрограммы. Использование state похоже на объявление автоматической переменной со словом static в C.

sub counter {
    state $c = 0;
    return ++$c;
}

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

(?<name>)
\K
\R
%+
%-
\g<name>

— Бинарный оператор defined-or (//). Возвращает первый из аргументов, который содержит определенное (не undef) значение. Может использоваться и в варианте с присвоением.

Следующие два примера иллюстрируют логику, которая часто прослеживается в сообщениях о вакансиях.

$city = $arg // 'Moscow';

$vacancy{city} //= 'Moscow';


Продолжение будет.

10+

| Комментариев: 6

На основе записей в трудовой книжке.

1999, Москва

— Я программирую на Perl. Особенность в том, одно и то же действие можно записать по-разному. Это и непривычно, и немного сложно, но интересно.

Это сказал мой товарищ, который в то время делал сайт одного из поставщика радиодеталей. Я же в то время писал на C++ программы для обработки данных физических экспериментов по сталкиванию частиц, делал статистический анализ данных, замаскированных шумом, и пытался применять новейшие математические приемы — вейвлеты — для анализа электрокардиограмм.

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

2000—2010, Москва

С этого года Perl стал меня кормить. За десять лет я совершенствовал себя и свои знания в журнале «Радио», фонде научных исследований «Прагматика культуры», студии Артемия Лебедева (да-да, там я тоже делал некоторые вещи на перле), российском информационном агентстве «РИА Новости», компании Q1 и в ООО «Гностик».

2010, Амстердам

В марте я подписал контракт с компанией Booking.com — еще одним лидером интернетов, который знает толк в перле и где не стыдно работать.

Из 49 ответов на вопрос «@var — это массив или список?», оставшихся после отсеивания накруток сторонников массивов, сложилась такая картина общественного мнения:

Trim

| Комментариев: 3

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

Вместо двух замен

$str =~ s/^\s+//;
$str =~ s/\s+$//;

Себастьян указывает на такой вариант:

$str =~ s/^\s*(.*?)\s*$/$1/;

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

$str =~ s/(^\s+|\s+$)//g;

$str =~ s/(?:^\s+|\s+$)//g;

$str =~ s/^\s*|\s*$//g;

$str =~ s/^\s+|\s+$//g;

P. S. В комментариях, кстати, видно, как почти одно и то же выражение разные люди записывают по-разному.

Страницы

  • img

Об архиве

Страница содержит архив записей за Март 2010, расположенных по убыванию.

Февраль 2010 — предыдущий архив.

Апрель 2010 — следующий архив.

Смотрите новые записи на главной странице или загляните в архив, где есть ссылки на все сообщения.