Последнее в категории CPAN

Часть 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';


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

Презентация А. Ш. блиц-доклада на «Перлбурге» про спан.

Lingua::RU::Inflect

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

Одна из приятных сторон в организации конференций — возможность получать удовольствие, косвенно (например, оплатив фуршет :-) участвуя в развитии перла и его приложений.

Александр Сапожников после блица Анатолия Шарифулина выложил на CPAN свой первый модуль Lingua::RU::Inflect, предназначенный для склонения русских имен.

Тест-драйв (с массой бойлерплейтов перед основным кодом :-):

use v5.10;
use utf8;
use open qw(:std :utf8);
use strict;
use Lingua::RU::Inflect qw(:all);

say inflect_given_name(GENITIVE, 'Андрей');

say join ' ', inflect_given_name(GENITIVE, 'Андрей', 'Борисыч');

Программа печатает

Андрея
Андрея Борисыча

Нелитературное Борисыч просклонялось правильно :-) Такой вот лингвоспан.

Perl 5.10 в 2010-м

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

Моя презентация на «Перлбурге».

Презентация в пяти частях, основное содержание — о том, как и зачем используют возможности 5.10 в новых модулях на CPAN и мои примеры вариантов применения, которые я показывал на onperl.ru.


View more presentations from andy.sh.

XSLT::Dependencies

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

Небольшая предыстория.

Верстка сайта Microsoft сделана на XSLT. Разумеется, многие XSLT-файлы зависимы от других, и при верстке довольно часто приходилось пересохранять неизмененный основной файл, хотя изменения делались где-то в другом файле, который подключался. А это напрягало.

Студийный parser долгое время тоже не умел обновлять кеш зависимых XSLT-шаблонов. Это тоже напрягало (хотя более напрягал, конечно, сам parser).

По мере возможности я стараюсь кешировать разобранные и скомпилированные XSLT-файлы. На спане есть модуль XSLT::Cache, который, однако, не отслеживает зависимости. Недостаток призван компенсировать модуль XSLT::Dependencies.

use XSLT::Dependencies;
my @dep_list = XSLT::Dependencies->new->explore('myfile.xslt');

В списке @dep_list оказывается перечень всех файлов, которые прямо или косвенно подключены к файлу myfile.xslt.

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

В todo числится обучить модуль читать XSLT не только напрямую из файла, но и из уже разобранного дерева XML::LibXSLT.

P. S. На типовом сайте, однако, отслеживать зависимости и не нужно: при разработке кешировать ничего не требуется, а на продакшне ничего не обновляется :-)

Geo::Horizon

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

Сегодня можно было бы написать про Google Buzz, но Perl API к нему еще не создан :-)

Зато на спане есть полезный модуль Geo::Horizon, который позволяет вычислить расстояние до горизонта. Расстояние прямой видимости зависит от широты, на которой находится наблюдатель, и от его роста.

Например, когда в центре Москвы (на широте около 55°) снесут все гостиницы и старые здания, человек ростом 180 см (вставшего на цыпочки, чтобы компенсировать расстояние от глаз до макушки) сможет видеть на расстоянии около пяти километров (что, в общем, сходится с тем, что говорили на уроках природоведения).

use v5.10;
use strict;
use Geo::Horizon;

say Geo::Horizon->new->distance(1.8, 55.7522); # 4794.73

При создании объекта типа Geo::Horizon возможно явно указать один из типов аппроксимации формы Земли, которые понимает модуль Geo::Ellipsoid, например:

my $gh = Geo::Horizon->new('WGS84');
say $gh->distance($height, $latitude);

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

say $gh->distance(318, 41.345278);              # 63677.53
say $gh->distance_great_circle(318, 41.345278); # 63675.51

Template::Semantic

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

Один из бешеных японцев™ — Наоки Томита — сегодня опубликовал на спане интересный модуль Tempalte::Semantic, один из немногих yet another-шаблонизаторов, на который стоит обратить внимание.

Сам шаблон представляет собой обычный HTML-фрагмент, а данные в него подставляются из хеша, структура которого похожа на описание правил CSS или путей XPath. Важно, что в HTML-код шаблона не требуется вписывать никаких искусственных конструкций для интерполяции переменных.

Например, чтобы вывести заголовок на страницу, сначала создаем HTML-заготовку:

<html>
    <head>
        <title></title>
    </head>
</html>

А затем описываем правила а-ля CSS:

use v5.10;
use strict;
use Template::Semantic;

say Template::Semantic->process(
    'title.html',
    {
        'html title' => 'My Title',
    }
);

Эта программа напечатает HTML-код с подставленным заголовком:

<html>
    <head>
        <title>My Title</title>
    </head>
</html>

Fantastique!

Описания с CSS-селекторами или XPath-адресами допустимо создавать и более сложной структуры, в том числе с вложенными хешами и списками (последние позволяют размножать фрагменты HTML-шаблонов).

Примеры наглядно описаны в документации модуля, а кроме того собраны в отдельном файле Template::Semantice::Cookbook.

Геометрические построения на поверхности Земли — хитрая штука, которая выглядит необычно, когда ее проецируют на плоскость. Кратчайшее расстояние между двумя городами в большинстве случаев превратится в дугу, по разному изогнутую в северном и южном полушариях. Прямыми останутся только линии, прочерченные с севера на юг.

На спане есть модуль с длинным названием Geo::GoogleEarth::Pluggable::Plugin::GreatCircle, который помогает рассчитать траекторию: по двум заданным точкам он формирует список точек, которые отрезками прямых с той или иной точностью рисуют кратчайший путь по поверхности планеты.

Эта программа печатает координаты 93-х точек между Москвой и Киевом.

use v5.10;
use strict;
use Geo::GoogleEarth::Pluggable;

my @moscow = (55.7522, 37.6156);
my @kiev = (50.4333, 30.5167);

my $arc =
   (new Geo::GoogleEarth::Pluggable)->GreatCircleArcSegment(
    startPoint => {lat => $moscow[1], lon => $moscow[0]},
    endPoint   => {lat => $kiev[1],   lon => $kiev[0]}
);

for (@{$arc->coordinates}) {
    say $_->lat, ', ', $_->lon;
}

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

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

Модуль в действии дает результаты, которые иной раз кажутся невозможными (как то лететь из Казахстана в Америку через Северный полюс), но если проложить кратчайший путь на реальном глобусе, то все сходится.

А вот как выглядит путь Харьков — Хабаровск.

Расстояние между Харьковом и Хабаровском

Search::Query

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

Разбор строки поискового запроса — задача, которая быстро превращается в головную боль, как только захочется ввести синтаксис запросов. Если фразы типа +театр -большой разобрать еще просто, то при обработке запроса театр & ((малый & москва) | (большой & урюпинск)) без грамматики не обойтись.

В январе 2010 на спане появился модуль Search::Query, который на первый взгляд поможет разрулить некоторые проблемы разбора поисковых запросов и даже подготовить подзапросы для последующих обращений к собственно поиску и склеиванию методами MapReduce.

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

Разбор строки выполняет инстанс $parser типа Search::Query::Parser. (Сам класс Search::Query не содержит рабочую логику.)

use Search::Query;

my $parser = Search::Query->parser();

Затем вызывают метод parse, передав ему поисковый запрос.

my $query = $parser->parse('большой театр');

Возвращаемое значение — значение типа Search::Query::Dialect::Native. Оно может быть преобразовано в строку (это поможет, например, визуально проконтролировать правильность разбора), хотя в простейшем случае она не сильно отличается от запроса:

+:большой +:театр

Кроме того, возможно пройтись по построенному дереву запроса, вызвав метод walk():

say $query->walk(\&my_walk);

Функция, ссылку на которую получает метод walk(), получает четыре параметра, содержащие объяснение частей запроса.

sub my_walk{
    my ($clause, $dialect, $code, $prefix) = @_;
    . . .
}

Модуль Search::Query позволяет создавать и собственные диалекты поисковых языков, наследуя их от Search::Query::Dialect, либо определяя типовые конструкции при создании парсера:

my $parser = Search::Query->parser({
        and_regex => 'И',
        or_regex  => 'ИЛИ',
        not_regex => 'НЕ',
    });

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

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

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

Мне хочется, чтобы на входе был UTF-8, и не разрывались части предложения типа А. С. Пушкин, а еще лучше — зал им. А. Пушкина.

Text::Sentence

Модуль входит в состав комплекта HTML::Summary. Без установки локали в русских текстах лихо пропускает половину точек (да, я нагло тестировал юникод).

use Text::Sentence qw(split_sentences);

my @s = split_sentences($text); # возвращается список

Lingua::EN::Sentence

use Lingua::EN::Sentence qw(get_sentences);

my $s = get_sentences($text); # возвращается ссылка на список

Несмотря на название, модуль уверенно выделяет русские предложения, и не разбивает инициалы. Не прошел тест на немецкую дату 30. Dezember (разбил на точке), но на это есть другой модуль. Зал им. А. С. Пушкина поделил на части после им.

Lingua::DE::Sentence

use Lingua::DE::Sentence;

my $s = get_sentences($text); # ссылка на список

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

Text::ToSentences

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

use Text::ToSentences qw(convert);

my $s = convert($text);

Функция convert возвращает ссылку на список предложений.

Здесь все хорошо с юникодом, но из зала им. А. С. Пушкина получислоь четыре предложения.

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

P. S. Это была история о том, почему рождаются велосипеды :-)

Страницы

  • img

Об архиве

Эта страница содержит последние записи категории CPAN.

Следующая категория — Веб.

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