Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие...

100
pragmaticperl.com 03/2015 Pragmatic Perl 25

Transcript of Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие...

Page 1: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

pragmaticperl.com03/2015

PragmaticPerl

25

Page 2: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Pragmatic Perl 25

pragmaticperl.com

Выпуск 25. Март 2015

Page 3: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Другие выпуски и форматы журнала всегдаможно загрузить с pragmaticperl.com. С во-просами и предложениями пишите на почту[email protected].

Комментарии к каждой статье есть в html-версии. Подписаться на новые выпуски можнопо ссылке pragmaticperl.com/subscribe.

Авторы статей: Андрей Шитов, Владимир Лет-тиев, Александр Ружников

Обложка: Марко Иванык

Корректор: Андрей Шитов

Выпускающий редактор: Вячеслав Тиханов-ский

Ревизия: 2015-03-02 09:40

© «Pragmatic Perl»

Page 4: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Оглавление

1 От редактора. Два года жур-налу . . . . . . . . . . . . . . . 1

2 Подключение в Mojoliciousмодели для бизнес-логики . . 4

3 Мутационное тестирование . 19

4 Про переменные и сигнату-ры в Perl 6 . . . . . . . . . . . . 32

5 Модули в Perl 6 . . . . . . . . . 49

6 Обзор CPAN за февраль 2015 г. 61

7 Интервью с ВладимиромЛет-тиевым . . . . . . . . . . . . . . 73

Page 5: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

1 От редактора. Два года журналу

Друзья! Нашему журналу исполняется двагода с первого выпуска. Поздравляем вас инас с этим событием. Подведем итоги двухлет.

За прошлый год мы выпустили без пере-рывов и почти вовремя 12 номеров, взялиинтервью у известных в Perl-сообществепрограммистов, авторов книг, организа-торов конференций. В создании журналапоучаствовали 29 авторов. Совместнымиусилиями авторов, корректоров и редакто-ров подготовили 1479 страниц текста!

Мы провели опрос, по результатам которо-го были составлены рекомендации для ав-торов. Читатели в целом оценили журналхорошо. Подписалось на рассылку по email

Page 6: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

— 1141 человек, по rss — 194. Присоединяй-тесь!

У сайтажурнала было около 105 000 посеще-ний, из которых 45 000 были уникальными.Журнал был скачан 60 000 раз.

География (top 10):

• Россия 64 171• Украина 21 273• Беларусь 2 965• США 2 081• Нидерланды 1 408• Казахстан 1 286• Германия 1 218• Велокобритания 1 021• Израиль 907• Литва 493

Page 7: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Друзья, журнал ищет новых авторов. Неупускайте такой возможности! Если у васесть идеи или желание помочь, пожалуй-ста, свяжитесь с нами.

Приятного чтения.

■ Вячеслав Тихановский

Page 8: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

2 Подключение в Mojolicious моделидля бизнес-логики

Рассмотрен вариант автоматическогоподключения классов моделей из указаннойдиректории

Mojolicious — фреймворк для написаниявеб-приложений, имеющий в своём арсе-нале много полезного функционала какпоначалу кажется, на все случаи жизни. Нокогда начинаешь с ним плотно работать ипытаться написать большое приложение,можно наткнуться на ситуацию, когданужные решения отсутствуют в базовомнаборе. Лично для меня недостатком мод-жо явилось отсутствие в нём моделей.Притом, что странно, данный функционалне реализован ни в самом моджо, ни вплагинах к нему, поиск по CPAN и в Гугле

Page 9: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

не выявил соответствующих плагинов.

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

Вкратце напомню, в чём суть MVC. При-ложение явно разделяется на три части:контроллер, модель и представление дан-ных. В контроллер поступают запросы отпользователя, и в них же ведётся предва-рительная обработка данных (выведениепереданных параметров, их валидация,проверка авторизации и пр.). Бизнес-логика и работа с базой данных вынесенав модель. Например, получение суммыбалланса пользователя из базы данных,услуги, подключенные у пользователя, ит.п. Полученные данные возвращаютсяобратно в контроллер и далее отобража-ются пользователю через представление

Page 10: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

(view). Как правило, для представленияиспользуются шаблонизаторы наподобиеTemplate::Toolkit. Контроллер в данной схе-ме выступает тонкой прослойкой междупользовательским запросом, моделью ипредставлением. В самом контроллере, какправило, бизнес-логику не размещают,иначе получаются «толстые уродливыеконтроллеры», в которых функционалразмазан и плохо поддаётся тестированию.

Итак, чего хочется? Хочется моделей как вCatalyst, чтобы из контроллера можно былоделать вызовы вида:1 sub my_controller {2 my $self = shift;34 # ...5 $self−>model('ModelName')−>

model_method;6

Page 11: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

7 # ...8 }

и чтобы фреймворк сам подгружал все мо-дели из соответствующей директории.

В моджо программисту самому предлагает-ся дописывать необходимый функционал(например, вынести в модули отдельнойдиректорией), либо писать обработкуданных и бизнес-логику прямо в контрол-лерах. Подобный подход применяется ввеб-фреймворках на других языках про-граммирования, например, laravel на php,flask на python и revel на Go.

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

Page 12: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

в моджо, которой хочу поделиться с ваминиже.

Реализация

Итак, для создания модели делаются сле-дующие шаги (покажу на примере новогоприложения):

• Генерим mojo-приложение: mojogenerate app MyApp && cdmy_app/lib.

• Создаём необходимые файлы идиректории: touch MyApp/Model.pm && mkdir MyApp/Model &&touch MyApp/Model/Base.pm.

• Правим MyApp.pm:

Page 13: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

1 package MyApp;23 use Mojo::Base 'Mojolicious';4 use MyApp::Model; # <−−

подключаем модуль с моделью56 sub startup {7 my $self = shift;89 #

################################################

10 # подключаем модель11 my $model = MyApp::Model−>new

(app => $self);1213 # создадим соответствующий

хелпер для вызова модели14 # из контроллеров15 $self−>helper(16 model => sub {17 my ($self,

$model_name) = @_;

Page 14: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

18 return $model−>get_model($model_name);

19 }20 );21 #

################################################

2223 my $r = $self−>routes;2425 $r−>get('/')−>to('root#index'

);26 }2728 1;

Правим MyApp/Model.pm:1 package MyApp::Model;23 use Mojo::Loader;4 use Mojo::Base −base;

Page 15: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

56 use Carp qw/ croak /;78 has modules => sub { {} };9

10 sub new {11 my ($class, %args) = @_;12 my $self = $class−>SUPER::new

(%args);1314 my $model_packages = Mojo::

Loader−>search('MyApp::Model');

15 for my $pm (grep { $_ ne 'MyApp::Model::Base' } @{$model_packages}) {

16 my $e = Mojo::Loader−>load($pm);

17 croak "Loading '$pm'failed: $e" if ref $e;

18 my ($basename) = $pm =~ /MyApp::Model::(.*)/;

Page 16: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

19 $self−>modules−>{$basename} = $pm−>new(%args);

20 }21 }2223 sub get_model {24 my ($self, $model) = @_;25 return $self−>modules−>{

$model} || croak "Unknownmodel '$model'";

26 }2728 1;

Правим MyApp/Model/Base.pm:1 package MyApp::Model::Base;23 use Mojo::Base −base;45 has 'app';6

Page 17: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

7 1;

Теперь подробнее о том, что было сделано.

В файле MyApp.pm мы создали объект клас-са MyApp::Model, которому в конструкторпередали текущий объект. Передача в кон-структор текущего объекта необходима длятого, чтобы потом из модели можно былообращаться ко всемметодам текущего клас-са.

В MyApp/Model.pm в конструкторе мынаходим все файлы в директории MyApp/Model/ используя класс Mojo::Loader иметод search. Тут необходимо уточнить,что Mojo::Loader не умеет рекурсивнообходить каталог, т.е. если директорияMyApp/Model имеет вид:1 MyApp/Model2 |_ModelFile.pm

Page 18: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

3 |_ModelFile2.pm4 |_MoreModel5 |_MoreModel1.pm6 |_MoreModel2.pm

то Mojo::Loader−>search('MyApp::Model') проигнорирует директориюMoreModel и загрузит модули только изкорневой директории. Как вариант, мож-но дополнительно в цикле перебрать всеподдиректории в корневой директориии скормить их также Mojo::Loader длязагрузки модулей.

Далее по коду. В конструкторе модели мыподгружаем каждый найденный модульс моделью (за исключением MyApp::Model::Base, о нём дальше) и загружаемего в хеш modules. Метод get_modelвозвращает класс, соответствующий запра-шиваемому, либо падает с ошибкой.

Page 19: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

В файле MyApp/Model/Base.pm мы указы-ваем все методы, которые будут наследо-ваться остальными моделями. Исходя изназвания становится понятно, что это ро-дительский класс для остальных модулейс моделями. Строка1 has 'app';

говорит о том, что необходимо представитьэлемент объекта1 $self−>{app}

как метод класса. Т.е. вызов $self−>app−>config равносилен $self−>{app}−>config. Это синтаксический сахар отсоздателя моджо.

Что такое app можно понять, взглянув накод модуля MyApp.pm. Это объект самоговерхнего класса MyApp.pm, который мы

Page 20: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

передали в конструктор.

Теперь приведём пример простейшего мо-дуля с моделью, например, MyApp/Model/MyModel.pm:1 package MyApp::Model::MyModel;23 use Mojo::Base 'MyApp::Model::

Base';45 # получить все данные из конфига6 sub get_config_data {7 my $self = shift;89 return $self−>app−>config;

10 }1112 1;

Вызвать данный метод из контроллера лег-че лёгкого:

Page 21: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

1 my $config = $self−>model('MyModel')−>get_config_data;

В данном случае будет вызван хелперmodel, определёный в методе MyApp::startup. Данный хелпер вернёт вызовметода get_model объекта класса MyApp::Model.

Ну вот и всё. Как видите, ничего особо слож-ного нет. Я надеюсь, что через некторое вре-мя у меня дойдут руки оформить это всё ввиде плагина для моджо, так как с ним впоследнее время я работаю довольно актив-но, и писать один и тот же код постоянноутомляет. По крайней мере, проект на гит-хабе под это дело уже создал :)

У кого есть вопросы, задавайте их в коммен-тариях.

Page 22: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Дополнительные материалы:

• Mojo documentation• Что такое helper в моджо• Mojo example apps• Пара хороших статей о моджо на хаб-ре

■ Александр Ружников

Page 23: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

3 Мутационное тестирование

Еще один способ сделать Perl-код качествен-нее — мутировать тесты для нахождениянепротестированного кода

Мутационное тестирование — способ про-верки качества тестовых наборов путемвнесения случайных изменений в тести-руемый код. Если после таких измененийтесты все еще проходят, значит они недо-статочно качественны, т.е. не полны.

Чтобы понять, зачем это нужно и какэто проверять, рассмотрим следующийпример:1 package Temp;23 use strict;4 use warnings;

Page 24: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

56 sub new {7 my $class = shift;8 my (%params) = @_;9

10 my $self = {};11 bless $self, $class;1213 $self−>{critical} = $params{

critical};1415 return $self;16 }1718 sub is_critical {19 my $self = shift;20 my ($temp) = @_;2122 return $temp >= $self−>{

critical};23 }2425 1;

Page 25: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Данный класс возвращает флаг, сигнали-зирующий о критической температуре.Тест для него был написан не очень вни-мательным программистом и выглядитследующим образом:1 use strict;2 use warnings;34 use Test::More;5 use Temp;67 my $temp = Temp−>new(critical =>

32);89 ok $temp−>is_critical(32);

1011 done_testing;

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

Page 26: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

пробуем посмотреть на покрытие кода те-стами, используя Devel::Cover:1 $ PERL5OPT=−MDevel::Cover prove t

&& cover2 lib/Temp.pm

100.0n/a n/a 100.0 0.0

100.0

Покрытие 100%. Таким способоммыничегоне выявили. Неужели нельзя каким-то об-разом автоматически выявлять подобныепроблемы, без участия человека? Можно!Здесь нам и пригодится мутационноетестирование.

Задача мутационного тестирования на ос-нове исходного класса, скрипта, да вообщелюбого кода, — сгенерировать нескольковариантов, где случайным образом изме-нить операторы, ключевые слова, удалить

Page 27: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

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

В описанном примере при мутации опера-тор >= будет заменен, например, на <=, итесты все также будут проходить, таким об-разом выявляя свои недостатки.

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

Page 28: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Как отпарсить Perl

Как можно проводить мутации? Можно,конечно, использовать регулярные вы-ражения, однако на практике разбиратьPerl-код с помощью регулярных выраже-ний невозможно без высокой доли ложныхсрабатываний, ошибок и прочего. Гораздоболее надежный способ — это использоватьPPI.

Несмотря на известное выражение “Onlyperl can parse Perl” (“Только perl-интерпретаторможет отпарсить Perl-язык”), PPI работаетдовольно сносно для большинства приме-ров кода. Вот как, например, заменить вописанном выше классе оператор >= на <=:1 my $ppi = PPI::Document−>new('

Temp.pm');23 if (my $operators = $ppi−>find('

Page 29: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

PPI::Token::Operator')) {4 foreach my $operator (

@$operators) {5 if ($operator−>content eq

'>=') {6 $operator−>

set_content('<=');78 $ppi−>save('Temp.pm.

mutant');9 }

10 }11 }

Т.е. находим все операторы (токен PPI::Token::Operator), затем нужныйзаменяем на <= и сохраняем мутантапод новым именем. Можно проводитьи несколько мутаций, таким образомвыявляя практически непроявляющиесяошибки.

Page 30: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Для мутационного тестирования на CPANесть модуль Devel::Mutator. Для генера-ции мутантов необходимо указать, какиефайлы мутировать:1 $ mutator mutate −r lib/*

По умолчанию все мутанты складываютсяв директорию mutants. Ключ−r для рекур-сивного нахождения модулей.

Для запуска же самих тестов выполняетсякоманда test:1 $ mutator test

Это команда для каждого мутанта издиректории mutants запускает тестыиз текущей директории. По умолчанию,запускается prove −l t, но это можнопереопределить с помощью опции −−command. Успешность или неуспешность

Page 31: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

тестов проверяется по значению $?. Т.е.если вы используете нестандартные тесто-вые модули, достаточно делать exit(0) вслучае успеха или exit(255) или любоедругое значение при неудаче.

Во время выполнения тестов на экран вы-водится текущий мутант и статус выполне-ния тестирования, где ok означает, что те-сты не проходят, а not ok — наоборот. На-пример:1 $ mutator test2 (1/10) ./mutants/49606d6...009

cd7a2/MyClass.pm ... ok3 (2/10) ./mutants/3f9577f...3

fd5f5b9/MyClass.pm ... not ok4 (3/10) ./mutants/a7c40ad...

f05df2e4/MyClass.pm ... not ok5 (4/10) ./mutants/514abf0...8401

c2f3/MyClass.pm ... not ok6 ...

Page 32: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Еслимутант был запущен неуспешно, мож-но просто посмотреть, что было изменено икак это повлияло на тесты:1 diff lib/MyClass.pm mutants/49606

d6bcaaf550b6cf76abf009cd7a2/MyClass.pm

Из diff можно понять правильно ли былавыполнена мутация, стоит ли обращать наэто внимание. diff может показываться иавтоматически, если указать опции −v, такможно сразу видеть, где проблема:1 $ mutator test −v2 (1/10) ./mutants/3

f9577f3d44ac20732b6340d3fd5f5b9/MyClass.pm ... not ok

3 628c6284 < my @related = @_ == 1 ? ref

$_[0] eq 'ARRAY' ? @{$_[0]} :($_[0]) : ({@_});

5 −−−

Page 33: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

6 > my @related = @_ != 1 ? ref$_[0] eq 'ARRAY' ? @{$_[0]} :($_[0]) : ({@_});

После выполнения всех тестов выводитсяобщий результат. Например:1 Result: FAIL (31/38)

или1 Result: PASS

Таким образом с помощью модуля Devel::Mutator можно протестировать сами те-сты и понять, как их можно улучшить, темсамым повысив качество программы в це-лом.

Page 34: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Недостатки

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

Еще одним недостатком является веро-ятность создания бесконечных циклов.Для борьбы с этим в Devel::Mutatorтесты запускаются с timeout, который поумолчанию равен 10 секундам.

Page 35: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

■ Вячеслав Тихановский

Page 36: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

4 Про переменные и сигнатуры в Perl 6

В этой статье описаны интересные синтак-сические возможности Perl 6, о которых небыло упомянуто в прошлый раз

Обновитесь

21 февраля появился релиз Rakudo Star2015.02. Одновременно объявлено, что этопоследний релиз с поддержкой Parrot.Дальнейшая разработка будет вестись ис-ключительно под виртуальную машинуMoarVM.

Page 37: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Лексические переменные

Лексические переменные в Perl 6 ведутсебя так, как и должны :-) Если попытатьсяиспользовать пременную вне блока, в ко-тором она определена, возникнет ошибка.В Perl 5 ошибка возникнет лишь при нали-чии use strict или при указании версии,в которой strict заработает сам, напри-мер: use v5.12. В Perl 6 все работает сразу,и при попытке обратиться к переменнойвне области ее видимости появится ошибкаVariable '$x' is not declared.1 {2 my $x = 42;3 say $x; # OK4 }56 #say $x; # Не OK

Page 38: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Лексические переменные, тем не менее,возможно удачно использовать в замы-каниях. В следующем примере функцияseq() возвращает блок, в котором исполь-зуется переменная, определенная внутрифункции:1 sub seq($init) {2 my $c = $init;34 return {$c++};5 }

После вызова функции эта переменнаяне только не исчезнет, но и сохранитсвое значение, что хорошо видно припоследующих вызовах:1 my $a = seq(1);23 say $a(); # 14 say $a(); # 25 say $a(); # 3

Page 39: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Возможно создать две независимые копиилокальной переменной:1 my $a = seq(1);2 my $b = seq(42);34 say $a(); # 15 say $a(); # 26 say $b(); # 427 say $a(); # 38 say $b(); # 43

state-переменные

Отдельно нужно упомянуть state-переменные. Они появились в Perl 5.10 иработают так же, как и в Perl 6. Переменная,объявленная с ключевым словом stateвнутри функции, инициализируется припервом вызове и сохраняет значение при

Page 40: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

повторных обращениях к функции.

При этом нужно понимать, что создаетсядействительно один-единственный экзем-пляр переменной. Если вернуться к приме-ру со счетчиком и использовать там stateвместо my, то возвращаемое замыкание бу-дет обращаться к одной и той же перемен-ной.1 sub seq($init) {2 state $c = $init;34 return {$c++};5 }

Сколько бы не создавалось счетчиков:1 my $a = seq(1);2 my $b = seq(42);

Все они будут являться одним и тем же:

Page 41: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

1 say $a(); # 12 say $a(); # 23 say $b(); # 34 say $a(); # 45 say $b(); # 5

Динамические переменные

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

Динамические переменные помечаютсявторым сигилом (твигилом) * (с намекомна wildcard).

Page 42: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

В следующем примере функция echo() пе-чатает динамическую переменную $*var,которая не только не определена в самойфункции echo(), но и не является глобаль-ной переменной в программе. Тем не ме-нее, имя резолвится при вызове из другихфункций, в каждой из которых есть своя пе-ременная с таким именем:1 sub alpha {2 my $*var = 'Alpha';3 echo();4 }56 sub beta {7 my $*var = 'Beta';8 echo();9 }

1011 sub echo() {12 say $*var;13 }14

Page 43: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

15 alpha(); # Alpha16 beta(); # Beta

Анонимные блоки

В Perl 6 есть понятие arrow blocks (илиpointy blocks) — это такие анонимныеблоки-замыкания, которые возвращаютссылку на функцию и могут приниматьаргументы.

Синтаксически они снабжаются стрелкой−>, за которой следует список аргументови блок кода:1 my $cube = −> $x {$x ** 3};2 say $cube(3); # 27

Здесь сначала создается блок {$x ** 3},принимающий один аргумент $x, а за-

Page 44: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

тем делается вызов, аналогичный вызовуфункции через указатель на нее: $cube(3).

Такие блоки со стрелкой удобно использо-вать в циклах:1 for 1..10 −> $c {2 say $c;3 }

Фактически, for здесь принимает спи-сок 1..10 и блок кода с аргументом $c,хотя сначала может показаться, что этаконструкция — синтаксис для циклов. Вследующем разделе мы вернемся к этомупримеру, но уже без использования явнойпеременной (и поэтому без стрелки).

Список аргументов вполне может состоятьи более чем из одного элемента:1 my $pow = −> $x, $p {$x ** $p};2 say $pow(2, 15); # 32768

Page 45: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

То же самое применимо и к спискам:1 for 0..9 −> $i, $j {2 say $i + $j;3 }

В этом случае за один проход цикл бу-дет поглощать сразу по два значения.Тело цикла отработает пять раз, печатаяпопарно сумму соседних цифр: 1, 5, 9 и т.д.

Плейсхолдеры

При создании анонимного блока кода, да-же такого, который будет принимать аргу-менты, объявлять их необязательно. Perl 6разрешает сразу использовать их подобнопредопределенным переменным $a и $b вPerl 5.

Page 46: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

В Perl 6 такие переменные должны бытьснабжены твигилом ^, а порядок формаль-ных аргументов будет соответствоватьалфавитному порядку.1 my $pow = {$^x ** $^y};2 say $pow(3, 4); # 81

Фактические значения 3 и 4 окажутся, соот-ветственно, в переменных $^x и $^y.

А теперь вернемся к циклу и перепишемего тело без использования явных аргумен-тов:1 for 0..9 {2 say $^n2, $^n1;3 }

Обратите внимание, что, во-первых, блоккода начинается сразу без предваряющейего стрелки, а переменные $^n1 и $^n2

Page 47: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

упоминаются в коде не в алфавитном по-рядке, но при этом получают правильныезначения, как если бы они были указаны всигнатуре функции в виде ($n1, $n2).

Наконец, плейсхолдеры могут быть име-нованными, вся разница в использованиивнутри блока кода заключается в твигиле— теперь это двоеточие ::1 my $pow = {$:base ** $:exp};2 say $pow(:base(25), :exp(2)); #

625

Порядок значений при вызове функции те-перь не имеет значения. Следующий вызоввернет тот же результат:1 say $pow(:exp(2), :base(25)); #

625

Page 48: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Переопределение функций

Ключевое слово multi позволяет опреде-лить несколько функций с одним именем,которые различаются списком своих аргу-ментов (сигнатурой). В Perl 6 аргументыфункций указывают сразу в заголовке, при-чем, как и обычные переменные, аргумен-ты могут быть типизированы (собственно,без указания типа мультифункции теряютсмысл).1 multi sub twice(Int $x) {2 return $x * 2;3 }45 multi sub twice(Str $s) {6 return "$s, $s";7 }89 say twice(42); # 84

10 say twice("hi"); # hi, hi

Page 49: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Работа этого примера довольно очевидна:когда передано целочисленное значение,вызывается twice(Int), а когда строка —twice(Str).

Переопределение с подтипами

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

В следующем примере созданы два подти-па: для четных и нечетных целых чисел.Условие отбора явно определено в блокепосле ключевого слова where.

Page 50: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Далее объявлены и определены две функ-ции с одним именем testnum, но с агру-ментами разных типов.1 subset Odd of Int where {$^n % 2

== 1};2 subset Even of Int where {$^n % 2

== 0};34 multi sub testnum(Odd $x) {5 say "$x is odd";6 }78 multi sub testnum(Even $x) {9 say "$x is even";

10 }

Теперь при вызове функции с именемtestnum будет выбрана одна из двух:testnum(Even) для четных чисел иtestnum(Odd) для нечетных:1 for 1..4 −> $x {

Page 51: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

2 testnum($x);3 }

Программа напечатает ожидаемую после-довательность строк, что говорит о том,что Perl 6 выбрал правильный вариантфункции, используя правила, заданныедля подтипов Odd и Even.1 1 is odd2 2 is even3 3 is odd4 4 is even

Продолжение следует

В этом номере журнала вас еще ждет статьяо модулях в Perl 6, а в следующем выпус-ке читайте о промисах (promises) и подроб-ный рассаказ о том, как работать с грамма-

Page 52: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

тиками (grammar).

■ Андрей Шитов

Page 53: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

5 Модули в Perl 6

Краткий обзор основныхмоментов, которыеполезно знать при работе с модулями в Perl6

Тем, кто знаком с модулями в Perl 5, без тру-да разберутся с тем, как использовать их вPerl 6. Тем не менее, есть несколько важныхотличий, которые необходимо знать передначалом работы.

Модули хранятся в файлах с тем же рас-ширением .pm. Точно так же организуетсяиерархия: модуль X::Y компилятор будетискать в файле X/Y.pm в одном из пред-определенных каталогов или в каталоге,указанном в опции −I при запуске изкомандной строки.

Page 54: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

В теории, имена модулей не обязаны бытьпривязаны к файлам (а на практике сейчасимя модуля, указанное в самом модуле,похоже, вообще не используется). Однакопока про это, видимо, лучше не думать.Еще одна интересная особенность, а имен-но, возможность хранить и подключатьодин и тот же модуль, но разных версий,пока в Rakudo не реализована.

module

Модуль объявляется ключевым словомmodule, за которым следует название. Воз-можны два варианта. Объявление можетбыть в виде директивы в начале файла, ивесь остаток файла будет телом модуля:1 module X;2

Page 55: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

3 sub x() {4 say "X::x()";5 }

Второй вариант — поместить тело модуля вблок:1 module X {2 sub x() {3 say "X::x()";4 }5 }

export

Переменные (my, our) и функции (sub),определяемые внутри модуля, по умолча-нию не видны за его пределами. Для того,чтобы экспортировать имя, необходимоуказать свойство (trait) is export:

Page 56: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

1 module X;23 sub x() is export {4 say "X::x()";5 }

Это все, что требуется для того, чтобыфункцией x() удалось воспользоваться впрограмме, которая будет использовать мо-дуль. Никаких многословных конструкцийи манипулирования массивами @EXPORT и@EXPORT_OK больше не требуется.

use

Подключение модуля — простая операцияс помощью ключевого слова use.

Сначала создаем файл Greet.pm:

Page 57: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

1 module Greet;23 sub hey($name) is export {4 say "Hey, $name!";5 }

А затем используем его:1 use Greet;23 hey("you"); # Hey, you!

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

Файл Greet/Polite.pm с модулем Greet::Polite:1 module Greet::Polite {2 sub hello($name) is export {3 say "Hello, $name!";

Page 58: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

4 }5 }

И программа, его использующая:1 use Greet;2 use Greet::Polite;34 hey("you"); # функция из модуля

Greet5 hello("Mr. X"); # из Greet::

Polite

import

Ключевое слово use автоматически вы-полняет импорт имен из подключаемогомодуля. Однако, если модуль определенв текущем файле в лексической областивидимости (обратите внимание, что мож-

Page 59: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

но указать модуль локальным, написавmy module), автоматический импорт непроизойдет, и придется сделать его явно:1 my module M {2 sub f($x) is export {3 return $x;4 }5 }67 import M;89 say f(42);

Без принудительного импорта (importM;) обращение к функции f() из модуляприведет к ошибке. Причем импорту под-вергнутся только имена, помеченные наэкспорт конструкцией is export.

Обратите внимание, что импорт проис-ходит при компиляции, поэтому имена

Page 60: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

станут доступны в программе даже вышестроки про импорт:1 my module M {2 . . .3 }45 say f(1);6 import M;7 say f(2);

need

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

Создаем модуль N с методом n() (метод со-здан как our—это важно, но без is export

Page 61: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

— а это не так важно):1 module N;23 our sub n() {4 say "N::n()";5 }

И теперь указываем, что нужен этот мо-дуль, а потом напрямую обращаемся к егометоду:1 need N;23 N::n();

Последовательность use M; import M;(именно в таком порядке) аналогичнаодному use M;.

Page 62: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

require

Ключевое слово require позволяет загру-зить модуль не во время компиляции (какэто делает use), а во время исполнения.

Для примера — модуль с единственнойфункцией, возвращающей сумму передан-ных ей аргументов:1 module Math;23 our sub sum(*@a) {4 return [+] @a;5 }

(Звездочка в *@a нужна, чтобы Perl свернулвсе аргументы в один массив, и можно бы-ло бы написать sum(1, 2, 3). Без звездоч-ки это станет синтаксической ошибкой, по-скольку метод будет ожидать массив, а не

Page 63: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

три скаляра.)

Теперь подключаем модуль с помощьюrequire и вызываем функцию:1 require Math;23 say Math::sum(24..42); # 627

Если попытаться вызвать Math::sum()до require, программа не сможет найтинужное имя. При этом импортироватьметод, написав import Math;, тоже неполучится, поскольку импорт происходитна этапе компиляции, то есть до того, какrequire загрузит модуль.

Page 64: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Заключение

Для удобства, вот список ключевых словPerl 6, которые потребуются при работе смодулями:

• use—загрузка и импорт на этапе ком-пиляции;

• need— загрузка без импорта на этапекомпиляции;

• import — импорт имен из загружен-ного модуля на этапе компиляции;

• require — загрузка без импорта вовремя исполнения.

■ Андрей Шитов

Page 65: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

6 Обзор CPAN за февраль 2015 г.

Рубрика с обзором интересных новинок CPANза прошедший месяц.

Статистика

• Новых дистрибутивов — 202• Новых выпусков — 815

Новые модули

Crypt::U2F::Server

Модуль Crypt::U2F::Server являетсяобёрткой к C-библиотеке libu2f-server. Мо-

Page 66: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

дуль реализует серверную часть протоколаU2F, предназначенного для универсальнойреализации двухфакторной аутентифика-ции, когда пользователь помимо вводапароля в браузере использует ещё физи-ческое устройство (например, USB-донгл),которое доступно браузеру через специаль-ное Javascript API.

Plack::Middleware::Antibot

Antibot — это набор фильтров для PSGI-приложений, которые позволяют боротьсяс отправкой форм роботами:

• FakeField — проверка, что было от-правлено скрытое поле;

• Static — проверка, что был загру-жен статический файл (например,

Page 67: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

css-стили) до отправки формы;• TextCapcha — проверка, что была пра-вильно решена текстовая капча;

• TooFast — проверка, что форма былаотправлена очень быстро;

• TooSlow — проверка, что форма былаотправлена через большой интервалвремени.

Inline::Perl6

Inline::Perl6, как следует из названия,позволяет выполнять из Perl 5 код на язы-ке Perl 6, а также загружать модули и вы-полнять методы объектов Perl 6. Для рабо-ты модуля требуется установить Rakudo свключённым бекендом MoarVM.

Page 68: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Promises6

Promises6 — довольно любопытная реали-зация спецификации Promises/A+, предо-ставляющая синтаксис обещаний в соот-ветствии со спецификацией ECMAScript 6.Модуль требует для работы Perl не ниже5.20.0.

AnyEvent::TLS::SNI

AnyEvent::TLS::SNI — это модуль, кото-рый добавляет поддержку TLS-расширенияSNI в AnyEvent::TLS. Указав параметрhost_name, можно задать имя сервера, ккоторому будет производиться подключе-ние. Поддержка SNI работает только длястороны клиента.1 use AnyEvent::HTTP;

Page 69: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

2 use AnyEvent::TLS::SNI;34 AnyEvent::HTTP::http_get5 'https://www.goggle.com/',6 tls_ctx => {7 verify => 1,8 verify_peername => 'https

',9 host_name => 'www.google.

com'10 },11 ...

Обновлённые модули

Gtk2 1.2495

Обновление Perl-интерфейса к библио-теке Gtk2 вышло в конце января 2015,

Page 70: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

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

perl 5.20.2

Вышел корректирующий релиз стабиль-ной версии Perl 5.20.2.

• Обновлён модуль Data::Dumper,в котором исправлена проблемаCVE-2014-4330, приводящая к рекур-сии при дампе глубоко вложенныхструктур данных.

Page 71: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

• Исправлен крах в PerlIO::Sacalarпри задании файловой позиции запределами скаляра.

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

• Восстановлена работоспособностьсборки на платформах IRIX и Tru64.

• Исправлены несколько ошибок assertв отладочных сборках Perl.

• Исправлен крах при вызове gmtime() спараметром NaN.

• Исправлено переполнение буфера икрах при компиляции определённыхшаблонов в регулярных выражениях.

• Устранена утечка памяти в некоторыхрегулярных выражениях, появившая-ся в Perl 5.20.1.

Page 72: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Role::Tiny 2.000000

Вышел второй мажорный релиз модулядля создания классов-ролей Role::Tiny.Основное несовместимое изменение —теперь Role::Tiny не делает предупре-ждения фатальными для классов-ролей,созданных с его помощью. Прагмы strictи warnings по-прежнему включены.

strictures 2.000000

Вслед за Roly::Tiny новая версия прагмыstrictures отказывается от полной фата-лизации предупреждений. Следующие ви-ды предупреждений больше не вызываютаварийное завершение работы:

• exec

Page 73: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

• recursion• internal• malloc• newline• experimental• deprecated• portable

Mojolicious 6.0

Выпущен шестой мажорный релиз веб-фреймворкаMojolicious с кодовымназвани-ем «Clinking Beer Mugs» (звенящие пивныекружки). Вопреки традиции, разработчикине стали ждать мая (последние мажорныерелизы выпускались с промежутком око-ло одного года). Удалён внушительныйсписок устаревших методов, переимено-вано множество других методов. Будьте

Page 74: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

внимательны при обновлении.

Plack 1.0034

В новом релизе «суперклея» для веб-фреймворков Plack исправлена проблемав безопасности при использовании Plack::App::File на платформе Win32. Делов том, что в некоторых версиях Windowsвозможно использование больше двухточек в фрагменте пути для перехода ввышестоящие каталоги.

Compress::Bzip2 2.22

Вышел новый релиз обёртки к библиоте-ке сжатия Bzip2. Новая версия содержитисправление крупной утечки памяти,

Page 75: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

возникавшей при декомпрессии.

Perl::Critic 1.124

Новый релиз модуля для проверкиисходного Perl-кода на соответствиепринятым стандартам Perl::Critic

содержит обновление для политикиProhibitUnusedPrivateSubroutines(запрет на неиспользуемые приватныеподпрограммы), в которой появиласьвозможность задать исключение длянекоторых файлов с помощью опцииskip_when_using, если они используютопределённый модуль. Это может быть по-лезно для классов-ролей, где определённыеприватные методы могут использоваться вклассах, использующих эту роль.

Кроме того, политики RequireUseStrict

Page 76: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

и RequireUseWarnings теперь учиты-вают, что Moose, Moo, Mouse, Dancer,Mojolicious и некоторые другие модулиавтоматически включают прагмы strict иwarnings.

■ Владимир Леттиев

Page 77: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

7 Интервью с Владимиром Леттиевым

Владимир Леттиев (crux) — постоянный ав-тор журнала, модулей на CPAN, основательperlnews.ru

Как и когда научился программировать?

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

Page 78: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Классе в 7-м у меня появился мой первыйкомпьютер Дельта-С (клон ZX Spectrum).Там загружался сразу REPL с Бейсиком,поэтому поневоле любой пользователькомпьютера начинал программировать.Сначала я только играл в игры. Подав-ляющее число игр имело графическуюзаставку, на которой красовалась подпись«Cracked by Bill Gilbert». Мне тоже захо-телось крякать игры. Где-то за 4 месяцая успел купить и зачитать до дыр кни-ги по бейсику и ассемблеру Z80. Первойвзломанной игрой оказалась игрушка«River Rescue», где я, исследуя дизассем-бированный код, нашёл инструкцию подекременту счётчика жизней и заменилего пустой операцией. Потом по всемправилам оформил бейсик-загручик, по-местив код на строку 0 и закрыв его отвзгляда трюком с цветом фона. Попра-вил в графическом редакторе заставку на

Page 79: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

«Cracked by Vladimir Lettiev» и записална кассету. Вскоре компьютер сгорел отразряда статического электричества, и наэтом карьера юного хакера оборвалась…

Какой редактор используешь?

Сейчас я использую Vim. Как и многиея был в шоке от первого знакомства с vi.Какая-то команда, запущенная в рутовомшелле открыла мне конфигурационныйфайл в этом редакторе. Оно пищало, ми-гало и запортило мне конфиг, преждечем я смог убить его kill’ом в соседнемтерминале.

Сначала редактировал в mcedit, так как онбыл похож на Far, который я использовалпод Windows. Пробовал nano, joe, но потомвсё-таки сел и изучил vim. И вот лет 10 ис-пользую только vim. Из плагинов исполь-

Page 80: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

зую только Nerdtree, из тем предпочитаюdesert или wombat256mod.

Доводилось также сделать целый проектв Padre IDE. Адаптировал своё поведениетак, чтобы он не падал и, в принципе,был доволен им. Но, в любом случае, GUI-инструменты тяжело использовать черезssh-соединение, поэтому удобнее vim врядли что-то можно придумать.

Как и когда познакомился с Perl?

Кажется это был 2002 год. После окончанияуниверситета я остался там работать си-садмином и заодно учился в аспирантуре.Одной из первых задач, которая возник-ла передо мной, стало создание учётаинтернет-трафика пользователей. Мы ис-пользовали прокси-сервер Squid, и нужнобыло распарсить лог и выполнить расчёты.

Page 81: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Я скопировал файл в несколько гигабайтна свой компьютер. В университете мыизучали Паскаль, поэтому я написал наПаскале программу, проверил её на парестрочек лога, а потом запустил обработкувсего файла. После 15 минут ожидания яподумал, что что-то тут не так. Мой колле-га, который в то время писал cgi-скриптыдля веб-сайта университета, посоветовалпопробовать распарсить лог Перлом, т.к. онздорово подходит для работы с текстовымифайлами.

Я взглянул на пример кода и был непри-ятно удивлён, что для переменных ис-пользовалась закорючка $, почти какстроковые переменные в древнем БейсикеZX Spectrum. Но, тем не менее, я изучилсинтаксис по образцу какой-то готовойпрограммы, слепил простой цикл, кото-рый построчно читал файл, сплитил строку

Page 82: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

и проводил суммирование. Запустил про-грамму и подумал, чем бы заняться, покаона работает, но каково было моё удив-ление, когда программа завершилась всчитанные секунды. Это был шок. С техпор использую Perl для любых задач снеизменным успехом.

С какими другими языками интересноработать?

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

Язык С прекрасен. Он позволяет писатьбыстрые XS-подпрограммы для Perl.

Page 83: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Что, по-твоему, является самым боль-шим преимуществом Perl?

Perl позволяет очень быстро прототипиро-вать программы. Можно быстро начать пи-сать код, потом постепенно трансформиро-вать программу, разнося код по модулям/-методам, когда кодовая база начнёт расти.

Как-то я дорабатывал реализацию одногосетевого протокола на C, и это занялоуйму времени, особенно на отладке. Потомпередо мной встала задача обрабатыватьполучаемые данные прикладного уровняи записывать их в СУБД. Это уже явнотребовало языка более высокого уровня.Я за пару недель переписал реализациюпротокола на чистом Перле в отдельныймодуль и продолжил реализовывать ло-гику приложения. Уровень сложности ивремя разработки при переходе снизились

Page 84: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

на порядок.

Ещё Perl универсален. На нём можно пи-сать короткие однострочники, скрипты,модули и огромные проекты. Функцио-нальный стиль, ООП, DSL — Perl можноадаптировать под любой стиль програм-мирования. Perl позволяет менять свойсинтаксис, что позволяет на базе Perlстроить надстройки. Посмотрите на Rex —это отличный пример как можно писатьсжатые сценарии на языке более высокогоуровня на основе Perl.

Что, по-твоему, является самой важнойособенностью языков будущего?

Период полураспада. Мне кажется, что всеязыки будущего будут появляться и исче-зать. Вечным будет только C, так как на нёми будут писать новые языки.

Page 85: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Что думаешь о будущем Perl?

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

Perl по-настоящему свободный проекти принадлежит сообществу. Нет однойкомпании, узурпирующей направлениеразвития. Сообщество очень внимательнои дружелюбно к новичкам. Любой человекможет влиться в разработку и получитьмаксимальную поддержку. Perl имеет чёт-кий план регулярных релизов и здоровуюротацию ответственных за релизы. Такаяорганизация даёт +100500 к Viability.

Мне бы очень хотелось увидеть в буду-щем улучшенную организацию CPAN.

Page 86: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Мне кажется, что очень не хватает своегоGPG-сервера ключей для CPAN-авторов,которыми бы можно было подписыватьрелизы.

Просто напрашивается наличие аналогасервиса travis-ci, заточенного под Perl.Как обходной вариант есть специальныйхелпер, но если бы удалось создать специа-лизированную систему, которая объединитразрозненные системы Perl QA cpantesters,coverage и другие метрики исходного кода,то это было бы просто фантастикой.

Почему пишешь статьи для PragmaticPerl? Откуда берешь идеи?

Однажды я написал статью по настройкеPostfix и LDAP и опубликовал её на одномресурсе. Через полгода я по этой статьекак в первый раз настраивал новый сервер.

Page 87: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

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

Когда начал писать статьи для PragmaticPerl я понял, что можно изучать новыевещи, до которых никак не доходили руки,а статья — это отличный повод, а заодно ишпаргалка на будущее. Так, например, яразбирался с DBIx::Class, который бы ни вжизни по другому бы не изучил. Поэтомуя всем советую, если есть желание что-товыучить, то учите и параллельно пишитеконспект. Из конспекта получится хоро-шая статья, которую можно опубликоватьи получить плюс в карму. Все ваши ошиб-ки подметят и поправят — это уже избавитвас от прохода по граблям. Win-Win.

Что касается источников идей, то их два.Первый — это публикации в блогах, но-

Page 88: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

востях, рассылках. Если проскакиваеткакая-то интересная тема, я могу сделатьпометку и развить её в статью. Второйисточник — CPAN. Готовя обзор CPAN,я просматриваю список из порядка 1000модулей с их описанием и изменениями.Какой-то модуль или что-то, связанное сним может стать предметом для статьи.

Чем так заинтересовал HTTP2, что даженаписал реализацию Protocol::HTTP2? Накакой стадиинаходится этотмодуль?Чтотакое Shuvgey?

В начале 2014 года я прочитал книжкуIlya Grigorik «High-Performance BrowserNetworking». Там в частности рассказыва-ли о протоколе HTTP2, который был созданна основе протокола SPDY от Google. Я ираньше слышал о нём, но теперь прочитало том, как он устроен. Это показалось мне

Page 89: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

интересным и я подписался на рассылкуietf-http-wg, в которой обсуждался черно-вик стандарта нового протокола HTTP2.Довольно известные в мире веба людипредлагали новые фичи, делились своиммнением, звучали и критические отзывы,но в целом дискуссия была продуктивной.

Вскоре я уже знал про все существующиереализации и видел, что одна из существу-ющих реализаций на Perl’е уже безнадёжноустарела (по факту она толком и не работа-ла). Взглянув на код я понял, что там идётпривязка к IO::Async, а мне было интерес-но получить что-то работающее без привяз-ки к конкретным событийным фреймвор-кам. Так и началась работа над Protocol::HTTP2.

Мне очень понравился интерфейс Protocol::WebSocket, я взял его как основу, но

Page 90: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

потом даже ещё больше упростил. Первыйработающий релиз Protocol::HTTP2вышел уже в мае 2014 года, где был ре-ализован 12-й черновик спецификациипротокола. После этого спецификацияменялась уже только в сторону упрощения:с каждым новым черновиком я простоудалял куски кода.

Сейчас работа над спецификацией HTTP2официально завершена. Вот уже на дняхожидается официальный номер RFC, послечего начнётся, нет, не правильно, про-должится его экспансия в веб. Вот вампростой факт: Firefox 35 по умолчаниюподдерживает http2 (черновик 14), за месяцего функционирования обнаружили, что9% соединений к сайтам происходило поhttp2. Это говорит о том, что в отличиеот ipv6, http2 довольно быстро станетдоминирующим протоколом веба.

Page 91: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Protocol::HTTP2 в целом работоспо-собен, там есть несколько некритичныхнедоделок (например, приоритеты пото-ков), которые можно будет закрыть, кактолько на них появится минимальныйспрос.

В качестве примера реализации веб-сервера на основе Protocol::HTTP2 ясоздал Shuvgey — асинхронный однопоточ-ный PSGI веб-сервер на основе AnyEventс поддержкой протокола http2. Он похожна Twiggy, только работает с http2 и можетиспользовать TLS. Кстати, сайт проектакрутится именно на шувгее, что также даётвам возможность оценить работоспособ-ность серверной реализации http2. Чтобыего увидеть вам потребуется Firefox 35 илиChrome 40.

Вообще, Шувгей — это собирательное на-

Page 92: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

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

Как возникла идея perlnews.ru? Как дела спосещаемостью, какие дальнейшие пла-ны?

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

Page 93: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

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

Идея возникла в конце января, сайт зарабо-тал 2 февраля, 3 февраля его здорово про-пиарили на форуме и в рассылке PragmaticPerl, что дало 159 посещений 122 пользова-телей. Сейчас в среднем около 45 сеансовв день. Примерно 40 подписчиков по RSS.Треть посетителей приходит по ссылкам изтвиттера, ещё треть, по всей видимости, до-бавила ресурс в закладки.

По статистике около 62% посещений изРоссии, 13% Украина, 3,5% Беларусь, такженемного Нидерланды, США, Германия,Таиланд. После того, как был опубликованпересказ интервью Рикардо Сигнеса под-

Page 94: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

касту rebuild.fm, пост заметил Миягава инаписал в твиттере, что ему понравилось,прочитал его через Google Translate. Этовылилось в 23 хита из Японии, так что орусскоязычном новостном ресурсе о Perlузнали и в Японии.

В планах пока ничего экстраординарного.Думаю сделать опрос, чтобы выяснить, ка-кие темы более интересны читателям, что-бы скорректировать приоритеты. Отвечатьможно в комментариях к этому интервью :)

Какможнонаписатьновостьна perlnews.ru?

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

Исходный код сайта доступен на github –

Page 95: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

perlnews.ru. Из данного репозитория с по-мощью Statocles генерируется статическийсайт.

Чтобы добавить свою новость, исправитьопечатку или внести новый ресурс в пере-чень полезных русскоязычных ресурсов,нужно форкнуть указанный выше репо-зиторий, внести изменения и отправитьзапрос на слияние (pull request). Более по-дробная информация есть в README.md.

Есть ли какие-то другие проекты, о кото-рых хотел бы рассказать?

Есть проект реализации протокола TLSна чистом Perl Protocol::TLS, который наданный момент уже поддерживает версиюTLS 1.2. Смысл проекта состоит в том,чтобы уйти от зависимости на OpenSSL,который развивается очень уж неспешно и

Page 96: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

консервативно. Попробуйте обновить libsslв каком-нибудь CentOS до свежих версий споддержкой всех новых фич безопасности,шифров и последних версий протоколаTLS. Это практически нереальный квест,так как практически всё современноепрограммное обеспечение линкуется сlibssl.

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

Где сейчас работаешь? Сколько временипроводишь за написанием Perl-кода?

Я работаю в крупной энергетическойкомпании. Занимаюсь телекоммуникаци-ями, поддержкой средств мониторинга ипромышленных систем учёта.

Page 97: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

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

Вне работы программирую на Perl в основ-ном для своих открытых проектов на github.Но это происходит импульсивно, т.е. возни-кает вдохновение, пишешь код недели напролёт, а потом выгораешь и ждёшь оче-редного озарения.

Стоит ли советовать молодым програм-мистам учить сейчас Perl?

В первую очередь я бы посоветовал мо-лодым ребятам обратить внимание на

Page 98: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

свободное программное обеспечение. По-старайтесь выбрать такие программы иокружение, которые являются свободны-ми. Это может быть Linux или одна изсвободных BSD-систем. Выбирайте лю-бой свободный язык: Perl, PHP, Python,JavaScript и прочие. Свободный редакторVim/Emacs/Eclipse. Свободный браузер:Firefox, Chromium и другие. СвободнуюСУБД: PostgreSQL/MySQL и подобные. Нобез фанатизма (привет, Nvidia).

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

Perl стоит выучить, даже если вы не про-граммист. Он позволит вам запросторешать различные задачи.

Page 99: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

Вопросы от читателей

Надолго ли хватит сил на perlnews.ru?

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

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

Что значит crux?

Page 100: Pragmatic 25 Perlpragmaticperl.com/issues/25/pragmaticperl-25-ebook.pdf · Другие выпуски и форматы журнала всегда можно загрузить

В студенчестве я играл в одной блэк-метал-банде местной андерграунд-сцены, мы да-же записали один альбом, который назва-ли «crux anasta» (да, с опечаткой, правиль-но пишется «crux ansata»), это один из глав-ных символов древних египтян. Позже, ко-гда мне нужно было придумать свой пер-вый рабочий логин для linux, я взял этотприкольный короткий крукс.

■ Вячеслав Тихановский