PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой...

120

Transcript of PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой...

Page 1: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,
Page 2: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Pragmatic Perl 34

pragmaticperl.com

Выпуск 34. Декабрь 2015

Page 3: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

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

Авторы статей: Владимир Леттиев, Андрей Ши-тов, Денис Федосеев

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

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

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

Ревизия: 2015-12-31 10:36

© «Pragmatic Perl»

Page 4: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Оглавление

1 От редактора . . . . . . . . . . 1

2 Впечатления от воркшопаSaint Perl 2015 . . . . . . . . . . 2

3 Взгляд на 2015 г. . . . . . . . . 12

4 Управление модулями и пре-компиляция в Perl 6 . . . . . . 16

5 Perl 6-винегрет . . . . . . . . . 32

6 Использование Rust из Perl . 47

7 Обзор CPAN за ноябрь 2015 г. 90

8 Интервью с Дмитрием Ша-матриным . . . . . . . . . . . . 105

Page 5: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

1 От редактора

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

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

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

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

Page 6: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

2 Впечатления от воркшопа Saint Perl2015

Не изменяя традиции 19 декабря 2015 г. про-шёл седьмой ежегодный воркшоп Saint Perlдля всех любителей и профессионалов мираPerl в Санкт-Петербурге.

Дляменя незабываемые впечатления о кон-ференции начались ещё с момента прибы-тия в Санкт-Петербург: затянутое серымиоблаками небо, моросящий дождь и +6ºC.Необычно для середины декабря, да и по-следующие дни ставили температурные ре-корды.

В этом году конференция проходила наплощадке, предоставленной генеральнымпартнёром конференции — компаниейDataArt. На сайте конференции зареги-

Page 7: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Открыл конференцию Сергей Романов,поприветствовав слушателей и рассказаво плане конференции и намечающихсямероприятиях.

Первый доклад назывался «ПротоколHTTP/2. Зачем и как использовать в Perl»,и это был мой доклад. Мне трудно сказать,как восприняли доклад слушатели, но 40минут для меня пролетели незаметно.Большая часть доклада была посвящена

Page 8: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

протоколу HTTP: истории протокола, недо-статкам HTTP/1.1 и достоинствам HTTP/2.Затем проводился обзор реализаций дляPerl: подробно рассмотрен Net::Curl и егоработа сHTTP/2, а также Protocol::HTTP2— как возможная основа для реализацийклиентов и серверов с поддержкой HTTP/2.

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

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

Page 9: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Матвеев с докладом «Инструменты дляработы с изображениями в Perl».

В докладе был сделан обзор самых попу-лярных модулей Perl для работы с изоб-ражениями: ImageMagick, GraphicMagickи другие. Как обычно, вопрос выборамодуля возник в результате работы надпрактической задачей: написание своейсобственной капчи. Особо в докладе былвыделен модуль Imager, который в отличиеот других библиотек не требует установ-ленных C-библиотек с заголовками (чтоиногда доставляет проблемы при сборке нанекоторых дистрибутивах), так же написанс использованием C/XS, но собираетсябез проблем, работает быстрее, хоть и неподдерживает большого спектра форматов.Были представлены бенчмарки, в которыхтакже можно было сравнить различия вскорости работы модулей.

Page 10: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Далее был обеденный перерыв, а затемИлья, для которого нашли переходникдля видео-разъёма, смог подключить свойноутбук и показать доклад «Технологииасинхронного программирования». Пре-зентация была сделана с помощью Vroom— инструмента, позволяющего показыватьслайды в редакторе vim. Доклад шёл це-лый час и фактически объединил в себенесколько больших докладов по различ-ным техникам асинхронного программи-рования: это форки, треды и сопрограммы.Было рассказано, чем ужасны Perl тредыи почему Coro — это единственные нор-мальная реализация тредов (хотя это и несовсем треды в привычном понимании).Бенчмарки иллюстрировали различия в ра-боте различных реализаций асинхронныхтехник, как по нагрузке процессора, так ипо использованию памяти.

Page 11: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Следующим докладчиком был Денис Федо-сеев, который представил доклад «Легасиэто не страшно». Денис поделился опытомборьбы с огромным легаси-проектом, гденет ни тестов, ни разделения на пакеты, нидаже элементарного use strict (на этомместе особо чувствительные перловикидолжны упасть в обморок). Рассказал отехниках изоляции кода, способах веденияисправлений. Презентация была очень кра-сочной, позволяя целиком проникнутьсяатмосферой безысходности: живые мертве-цы, велосипеды с квадратными колёсами.Но в итоге был сделан вывод, что выживатьс легаси можно, и это не страшно.

После кофе-брейка выступил лидерMoscow.pm Павел Щербинин с докла-дом «Index Condition Pushdown», которыйбыл посвящён одноимённой фиче, кото-рая появилась в MySQL 5.6. Слайдов как

Page 12: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Доклад закономерно породил вопрос:зачем MySQL, если есть PostgreSQL, нофлейм был беспощадно отсечён — каждыйиспользует то, что его устраивает и в чёмон лучше разбирается.

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

• Artur Penttinen сделал сразу два блиц-

Page 13: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

доклада о том как можно распарситьконфигурационный файл одностроч-ником и частный случай с конфигура-ционным файлов в формате ini.

• Илья Чесноков, «О регулярности».Немного философский доклад особытиях в нашей жизни и фор-мировании полезных привычек,например, регулярное проведениеконференций или ежегодное ведениецикла рождественских статей PerlAdvent Calendar.

• Илья Чернов, «PSPlot — графикив EPS». Доклад был посвящён соб-ственной разработке: модулю psplot,который позволяет рисовать двумер-ные графики в формате EPS.

• Доклады Михаила Иванова «SWAT»и Алексея Мележика «SparrowHub»

Page 14: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

были логически объединены и по-священы системе Swat — DSL-языкуи утилитам для быстрой разработкиавтоматических тестов web прило-жений и его спутнику sparrowhub,служащего для хранения сцена-риев тестирования для наиболеепопулярных веб-приложений (типаwordpress).

• Сергей Романов в докладе «Christmasis coming» наконец упомянул то,что практически не звучало на кон-ференции: Perl 6. На рождество насвсех ждёт стабильный релиз Perl 6,которого так ждали последние 15 лет.

После окончания докладов последовалатрадиционная after party в одном из баровсеверной столицы (а для некоторых и не водном). Но это уже другая история, впечат-

Page 15: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

ления о которой трудно выразить словами,но можно измерить в единицах объёма ;-)

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

Page 16: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

3 Взгляд на 2015 г.

Краткий обзор заметных событий в миреPerl за прошедший год

1 февраля

На конференции FOSDEM в БрюсселеЛарри Уолл объявил, что официальнаябета-версия Perl 6 появится 27 сентября(на его 61-летие), а релиз 6.0 ожидается наРождество 2015-го.

Статья в журнале с заметками с этого вы-ступления: Perl 6, или Get ready to party.

2 февраля

Владимир Леттиев открыл сайт perlnews.ru— новостной блог о всех заметных событи-

Page 17: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

ях мира Perl на русском языке.

16 февраля

Разработчики Rakudo объявили, что пре-кращают поддержку виртуальной машиныParrot, чтобы не тратить силы на поддержа-ние бекенда, который все равно не сможетобеспечить некоторые нужные возможно-сти, которые потребуются в предстоящемрелизе Perl 6.0 в 2015 году.

6 апреля

The Perl Foundation объявили о созданиифонда поддержки развития ядра Perl 6 (Perl6 Core Development Fund).

28 апреля

Microsoft выпустил текстовый редактор для

Page 18: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

программистов Visual Studio Code. Средиязыков, для которых доступна подстветкасинтаксиса, — Perl и Perl 6.

1 июня

Вышел релиз Perl 5.22. Статьи в журнале:

• Что нового в Perl 5.22• Перевод документа perl5220delta.podна русский язык

6 июня

Марк Леман анонсировал свой форк Perl5.22, провокационно назвав его stableperl.

16 августа

20 лет CPANу.

Page 19: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

27 сентября

Perl 6 (в лице Rakudo Star 2015.09) официаль-но получил статус бета-версии.

18 декабря

Языку программирования Perl исполни-лось 28 лет.

25 декабря

Релиз Perl 6.

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

Page 20: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

4 Управление модулями и прекомпиля-ция в Perl 6

25 декабря 2015 г. вышел первый стабильныйрелиз Rakudo Perl 6, среди новшеств которо-го совершенно новая система управления мо-дулями и прекомпиляция. Рассмотрим в де-талях процесс загрузки, разрешения зависи-мостей и компиляции модулей.

Обычная загрузка модуля

Традиционный процесс загрузки модуля вPerl 5 выглядит достаточно просто: имя мо-дуля преобразуется к имени файла, напри-мер, Foo::Bar ожидается быть найденнымв файле Foo/Bar.pm. В массиве @INC содер-жится список каталогов, в которых следуетпроизводить поиск файлов модулей. Часть

Page 21: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

каталогов является фиксированными и по-лучили свои обозначения, например:

• site — каталог для поиска модулей,установленных администраторомсистемы,

• vendor — каталог для модулей, постав-ляемых с дистрибутивом,

• perl — каталог модулей, идущих в по-ставке Perl

Модули ищутся и загружаются во времякомпиляции программы из исходногокода на диске. Такой же метод до недав-него времени использовался и в Perl 6, норождественский релиз внёс существенныеизменения в такое положение вещей.

Page 22: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Репозитории

Теперь в Perl 6 мы работаем с репозитори-ями — определённым образом организо-ванное хранилище модулей. Репозиториимогут быть различных типов, и это первоеотличие от традиционных каталогов. Про-стейший вариант репозитория совместим страдиционным подходом и хранит файлымодулей в соответствии с именем пакета.Более сложный вариант поддерживаетустановку дистрибутивов модулей вместес метаинформацией и ресурсами, а такжепроизводит прекомпиляцию модулей вбайткод.

Ранее используемый массив @*INC ушёлв небытие и теперь при загрузке моду-лей используется переменная процессаPROCESS::<$REPO>, которая являетсясвязанным списком с информацией о

Page 23: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

доступных репозиториях.1 $ perl6 −e 'for $*REPO.repo−chain

−> $n { say $n }'23 inst#/home/user/.perl6/2015.124 inst#/usr/share/perl6/site5 inst#/usr/share/perl6/vendor6 inst#/usr/share/perl67 ...

Как видно, в отличие от Perl 5, в цепочкерепозиториев присутствует новый каталог,находящийся в каталоге пользователя,запустившего программу, и он имеетмаксимальный приоритет. Кроме того,присутствует префикс inst#, которыйуказывает на тип репозитория, в данномслучае тип CompUnit::Repository::Installation, который поддерживаетинсталляцию.

Page 24: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

По-прежнему мы можем дополнять списокс помощьюфлага−I или переменной окру-жения PERL6LIB, например:1 $ perl6 −I /opt/perl6 'for $*REPO

.repo−chain −> $n { say $n }'23 file#/opt/perl64 inst#/home/user/.perl6/2015.125 inst#/usr/share/perl6/site6 inst#/usr/share/perl6/vendor7 ...

Как видно, если не указать тип репозито-рия перед путём, то он будет считаться тра-диционным файловым file#.

Что касается выражения use lib '/path/to/lib', то теперь её нельзя использоватьв модулях, только в скриптах.

Page 25: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Инсталляция в репозиторий

Инсталляция в традиционный файловыйрепозиторий — это простое копированиефайлов. С новым типом репозиториявсё несколько сложнее. Рассмотрим какорганизован такой репозиторий:1 \2 +− dist3 |4 +− sources5 |6 +− resources7 |8 +− short9 |

10 +− precomp11 \12 + compiler.id13 \14 + ..

Page 26: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

При инсталляции дистрибутива Foo, со-держащего модуль Foo::Bar, в каталогеdist создаётся файл с именем, представля-ющим собой SHA1 от уникального иден-тификатора дистрибутива, содержащийметаинформацию о дистрибутиве в фор-мате JSON. В каталог sources помещаютсяисходные коды модуля, в каталог resource- связанные ресурсные файлы, все именафайлов генерируются как уникальные40-символьные идентификаторы.

В каталог short помещаются файлы с име-нами как результат хеш-функции SHA1 отимени соответствующего модуля. В такомфайле помещается 40-символьный иденти-фикатор дистрибутива, в состав котороговходит данный модуль.

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

Page 27: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Внутри каталога precomp создаётся каталогдля текущей версии компилятора (в имявключается даже время сборки компилято-ра). Дальнейшая организация вложенныхкаталогов precomp напоминает git: внутрисоздаётся до 256 двухбуквенных каталогов,в который помещаются скомпилирован-ный байткод, например:1 +− 5C2 \3 + 5

C74B123E79B373BB96EC583A5C7EE4F458931BD

4 + 5C74B123E79B373BB96EC583A5C7EE4F458931BD.deps

5 + 5C74B123E79B373BB96EC583A5C7EE4F458931BD.rev−deps

6 +− 7E7 \8 + 7

Page 28: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

E4AC40F59629C48CCBD390FEB4B272004591024

9 + 7E4AC40F59629C48CCBD390FEB4B272004591024.deps

10 + 7E4AC40F59629C48CCBD390FEB4B272004591024.rev−deps

Создаются также файлы .deps и .rev-deps ку-да помещается данные о зависимостях и об-ратных зависимостях (sha1-хеш имени мо-дуля).

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

1. вычисляет sha1-сумму имени Foo::Bar;

Page 29: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

2. ищет файл с получившимся id в ката-логе short;

3. если находит, то по содержимомуузнаёт id дистрибутива;

4. загружает метаинформацию дистри-бутива из каталога dist;

5. из метаинформации узнаёт располо-жение исходного кода нужного моду-ля дистрибутива;

6. проверяет наличие исходного кода вкаталога sources (но не загружает);

7. проверяет наличие прекомпилиро-ванного кода в precomp;

8. если нет прекомпилированного кода,то выполняет загрузку исходного ко-да и прекомпиляцию с сохранениембайткода;

9. загружает из каталога precomp файлс прекомпилированным кодом моду-ля;

10. проверяет наличие в каталоге

Page 30: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

precomp файла с таким же именем,но с окончанием .deps;

11. если есть deps-файл, то находит в нёмимена source-файлов зависимостей;

12. в цикле проходит шаги 2–12 для всехзависимостей.

За инсталляцию отвечает класс CompUnit::Repository::Installation. Примеркода, выполняющего установку, можноувидеть в скрипте установки дистрибу-тива CORE при сборке Rakudo. В целомпримерно так:1 my %provides =2 "Foo::Bar" => "lib/Foo/Bar.

pm6",3 ;45 # задаём путь к репозиторию для

данного процесса

Page 31: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

6 PROCESS::<$REPO> := CompUnit::RepositoryRegistry

7 .repository−for−spec("inst#/path/to/repo");

89 # устанавливаем/прекомпилируем

10 $*REPO.install(11 Distribution.new(12 name => "Foo",13 auth => "vendor",14 ver => "0.1",15 provides => %provides,16 ),17 %provides,18 :force,19 );

Page 32: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Недостатки

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

$(DESTDIR)

Большинство дистрибутивов Linux иUNIX-систем используют переменнуюокружения $(DESTDIR), чтобы указатьвременный каталог для инсталляции присборке (например, при сборке пакетов).Новый механизм репозиториев затрудняетуказание временного префикса, поэтомувышедший Rakudo 2015.12 просто падает сошибкой при установке с использованием

Page 33: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

$(DESTDIR).

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

Прекомпиляция

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

Page 34: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

создаст необходимые файлы в каталогепользователя.

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

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

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

Page 35: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Rakudo 2016.01

16 января 2016 г. ожидается очередной ре-лиз Rakudo. Вероятно, что-то из обнаружен-ных проблем будет исправлено.

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

Page 36: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

5 Perl 6-винегрет

Новогодний оливье — сборная солянка про раз-ные интересные штуки в Perl 6

Юникод

Хранение и обработка символов внутристрок Perl 6 происходит в формате NFG(Normal Form Grapheme). Это названиепридумано еще в бытность Parrot, а с прак-тической точки зрения достаточно знать,что из любого символа можно получитьего NFC-, NFD-, NFKC- и NFKD-формы:-) Это разные канонические и декомпо-зированные представления символов вюникоде.

Подробности про разные формы представ-

Page 37: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

лений с интересными примерами опубли-кованы на сайте юникода, а история NFG —в блоге Джонатана.

Посмотреть разные формы помогут одно-именные методы, которые можно вызы-вать на односимвольных строках:1 say $s.NFC; # codepoint2 say $s.NFD;3 say $s.NFKC;4 say $s.NFKD;

Полное каноническое название возвращаетметод .uniname:1 say 'й'.uniname; # CYRILLIC SMALL

LETTER SHORT I

У строк есть полезный метод .encode, поз-воляющий получить представление в тойили иной юникодной кодировке:

Page 38: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

1 my $name = 'Перл';2 say $name.encode('UTF−8');34 # utf8:0x<d0 9f d0 b5 d1 80 d0 bb

>

(Этот метод не поможет перекодироватьCP1215 в КОИ-8.)

Для закрепления материала предлагаю по-смотреть на вывод упомянутых методов наразных хитрых символах:1 unidump('�');2 unidump('ы');3 unidump('å');4 unidump('é');5 unidump('�'); # один из немногих

символов,6 # для которого

различаются7 # все канонические

представления

Page 39: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

8 unidump('й');9 unidump('²');

10 unidump('Æ');1112 sub unidump($s) {13 say $s;1415 say $s.chars; # число графем16 say $s.NFC; # code point17 say $s.NFD;18 say $s.NFKC;19 say $s.NFKD;20 say $s.uniname; # юникодное

название буквы2122 say $s.NFD.list; # списком2324 say $s.encode('UTF−8').elems;

# сколько байтов25 say $s.encode('UTF−16').elems

;2627 say $s.encode('UTF−8'); # в

Page 40: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

виде utf8:0x<...>2829 say '';30 }

Формы NFKC и NFKD, в частности, могутпреобразовать надстрочные и подстроч-ные индексы в обычные цифры:1 say '2'.NFKD; # NFKD:0x<0032>2 say '²'.NFKD; # NFKD:0x<0032>

С помощью функции unimatch можноузнать, принадлежит ли символ к тойили иной группе символов в юникоде.Например:1 say unimatch('ф', 'Cyrillic'); #

True

Но нужно быть осторожным, чтобы не раз-жигать:

Page 41: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

1 say unimatch('ї', 'Cyrillic'); #True

2 say unimatch('ï', 'Cyrillic'); #False

Здесь были одинаково выглядящие, норазные символы. Их NFD соответственно 0x<0456 0308> и 0x<0069 0308>, а имена— CYRILLIC SMALL LETTER YI и LATINSMALL LETTER I WITH DIAERESIS.

Юникодные свойства можно проверить ирегулярными выражениями:1 say 1 if 'э' ~~ /<:Cyrillic>/;2 say 1 if 'э' ~~ /<:Ll>/; # Letter

lowercase

Для создания юникодных строк можнонапрямую воспользоваться конструкторомкласса Uni:1 say Uni.new(0x0439).Str; # й

Page 42: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

2 say Uni.new(0xcf, 0x94).Str; # Ï

Whatever (*)

Whatever — это класс, который позволяетсоздавать объекты, тип и значение кото-рых определяются из контекста. Чтобысоздать такой объект, достаточно поста-вить звездочку (если она, разумеется, неозначает умножение).1 say *.WHAT; # (Whatever)

Whatever удобно использовать для созда-ния простых функций, например:1 my $f = * ** 2; # возведение в

квадрат2 say $f(16); # 2563

Page 43: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

4 my $xy = * ** *; # возведение впроизвольную степень

5 say $xy(3, 4); # 81

Того же результата удастся достичь болеетрадиционным (для старого Perl 6) синтак-сисом:1 # Анонимный блок кода с одним

аргументом $x2 my $g = −> $x {$x ** 2};3 say $g(16);45 # Блок с двумя аргументами, имена

сортируются по алфавиту6 my $h = {$^a ** $^b};7 say $h(3, 4);

Вполне оправдано использование звездоч-ки для создания интервалов (Range):

Пример с циклом:

Page 44: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

1 for (5..*) {2 .say; # построчно печатает от

5 до 103 last if $_ == 10;4 }

Пример с массивом:1 my @a = <2 4 6 8 10 12>;2 say @a[3..*]; # (8 10 12)

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

Все, начиная с четвертого элемента и закан-чивая предпоследним:1 say @a[3..*−2]; # (8 10)

Чтобы получить последний элемент, нель-зя просто написать @a[−1]:

Page 45: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

1 Unsupported use of a negative −1subscript to index from theend;

2 in Perl 6 please use a functionsuch as *−1

Следует добавить звездочку:1 say @a[*−1]; # 12

Звездочка подходит и для создания лени-вых списков (то есть таких списков, очеред-ной элемент которых вычисляется по меренеобходимости):1 my @a = (1 ... *);2 for (0..5) {3 say @a[$_];4 }

В ленивых списках допустимо подсказатькомпилятору, как генерировать последова-

Page 46: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

тельность:1 my @a = (1, 2 ... *); # с

шагом 12 my @a = (2, 4 ... *); # четные

числа3 my @a = (2, 4, 8 ... *); #

степени двойки

Либо использовать явно определенныйблок со способом вычисления:1 my @fib = 0, 1, * + * ... *; #

Фибоначчи

Файлы

Имя файла, который сейчас исполняеся, те-перь находится в переменной $*PROGRAM−NAME, а не $*PROGRAM_NAME, как было ещесовсем недавно.

Page 47: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

А вот программа, которая использует встро-енную функцию slurp, читающую содер-жимое текущего файла:1 say slurp $*PROGRAM−NAME;

Противоположная функция — spurt(«бить струей»), она записывает данные вфайл. Вот пример реализации юниксовойфункции cp на Perl 6:1 my ($source, $dest) = @*ARGS;23 my $data = slurp $source;4 spurt $dest, $data;

По умолчанию файл либо создается, либоперезаписывается. Ключ (именованныйаргумент) :append попросит добавлятьновые данные в конец файла:1 spurt $dest, $data, :append;

Page 48: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Чтобы упасть с ошибкой при попытке за-писи в существующий файл, добавьте оп-цию :createonly (:append при этом ста-нет неактуальной):1 spurt $dest, $data, :createonly;

И slurp, и spurt принимают аргументс именем кодировки enc, но опять же,старых кодировок типа 'KOI8' там нет (даи не надо):1 my $data = slurp $source, enc =>

'UTF−8';2 spurt $dest, $data, enc => 'UTF

−16';

Если на строке вызвать метод .IO, то воз-вращается объект класса IO::Path. Методопределен так:1 method IO() returns IO::Path:D

Page 49: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

(:D здесь не ржачный смайл, а означаетdefined.)

Например, как получить абсолютный путьк локальному файлу:1 say 'file1.pl'.IO.abspath;

Как получить содержимое такого-то катало-га:1 say '.'.IO.dir;

Проверки существования файлов и катало-гов теперь выглядят так:1 say 1 if 'file.txt'.IO.e; # −e '

file.txt' в Perl 52 say 1 if 'file.txt'.IO.f; # −f3 say 1 if '..'.IO.d; # −d

Остальные методы, перечисленные вдокументации, вполне понятны без объяс-

Page 50: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

нений. Например, для выделения из именифайла расширения можно воспользоватьсяметодом .extension:1 say $filename.IO.extension;

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

Page 51: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Встраивание Rust в Perl с помощью FFI

Rust — язык системного программиро-вания, развиваемый Mozilla Fundation.Призван заменить собой С. Обеспечиваетбезопасную работу с памятью и прочиеприятные мелочи, которых иногда так нехватает в С, при этом не дает оверхеда попроизводительности (в теории).

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

Сначала установим Rust последней версии(1.5 на момент написания). Инструкциипо установке на все поддерживаемые

Page 52: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

платформы можно найти на сайте —https://www.rust-lang.org/downloads.html.

Будем считать, что Rust уже установлен идаже работает. Попробуем его использоватьиз Perl.

Сначала опробуем пример из документа-ции, создадим новый проект с помощьюCargo:1 cargo new embed2 cd embed

Добавим в Cargo.toml следующее содер-жимое:1 [lib]2 name = "embed"3 crate−type = ["dylib"]

Этим мы говорим карго, что мы хотим

Page 53: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Теперь отредактируем src/lib.rs и при-ведем его к такому виду:1 use std::thread;23 #[no_mangle]4 pub extern fn process() {5 let handles: Vec<_> = (0..10)

.map(|_| {6 thread::spawn(|| {7 let mut x = 0;8 for _ in (0..5

_000_000) {9 x += 1

10 }11 x12 })13 }).collect();14

Page 54: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

15 for h in handles {16 println!("Thread finished

with count={}",17 h.join().map_err(|_| "

Could not join athread!").unwrap());

18 }1920 println!("done!");21 }

Это приложение запускает 10 тредов, каж-дыйиз которых считает до 5 000 000, собира-ет от них возвращаемое значение (счетчикx) и выводит это нам.

Соберем его:1 cargo build −−release

В каталоге target/release у нас появит-ся файл libembed.so (дляMac OS расшире-

Page 55: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

ние будет dylib, для Win — dll, я все это про-делываю на маке, так что библиотеки вез-де будут с расширением dylib, вам же надобудет поправить под свою систему) — этонаша подключаемая библиотека. При фор-мировании библиотеки Cargo автоматиче-ски добавляет префикс lib к имени проек-та, указанного в name.

Настало время вызвать ее из Perl. Таккак XS-биндингов в Perl для Rust еще несуществует (ну или я их не нашел), то мыбудем использовать FFI::Raw. Этот модульпозволяет из кода на Perl дергать функ-ции в библиотеках на С. Модуль весьманизкоуровневый, но для начала это дажехорошо.

Создадим файл main.pl со следующим со-держимым:1 #!/usr/bin/env perl

Page 56: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

23 use v5.16;4 use FFI::Raw;56 my $process = FFI::Raw−>new(7 'target/release/libembed.dylib'

, 'process',8 FFI::Raw::void,9 );

1011 say $process−>call();1213 say "Done!";

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

И запустим наш перловый скрипт:

Page 57: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

1 alpha6$ perl ./main.pl2 Thread finished with count

=50000003 Thread finished with count

=50000004 Thread finished with count

=50000005 Thread finished with count

=50000006 Thread finished with count

=50000007 Thread finished with count

=50000008 Thread finished with count

=50000009 Thread finished with count

=500000010 Thread finished with count

=500000011 Thread finished with count

=500000012 done!13 Done!

Page 58: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Этот код может валиться с Segmentationfault 11 перед выходом из скрипта. Это

связано с выводом с STDOUT из кода наRust. Видимо, FFI как-то криво обрабатыва-ет закрытие дескрипторов. На маке валитсястабильно, на Linux работает без ошибок,на Windows не проверял. Видимо, влияюткакие-то особенности платформы.

Вызывать числодробилки из Perl это ко-нечно хорошо, но как насчет передачи па-раметров функции? Тоже можно, посчита-ем факториал.

Приведем src/lib.rs к виду:1 #[no_mangle]2 pub extern fn fact(x: i32) −> i32

{3 let mut fact = 1;4 for i in 1..x+1 {5 fact *= i;

Page 59: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

6 }78 return fact;9 }

Здесь мы объявляем публичную функциюfact, которая принимает на вход число ввиде 32-битного целого и то же самое воз-вращает в качестве результата.

Так же обратите внимание: #[no_mangle]надо указывать перед каждой функцией,которую мы хотим экспортировать. Еслиубрать эту строку и попробовать вызватьрассчет факториала, мы получим ошибку,несмотря на то, что функция объявленапубличной:1 alpha6$ perl ./main.pl2 dlsym(0x7ffeda40abd0, fact):

symbol not found at ./main.plline 13.

Page 60: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Приведем main.pl к виду:1 my $fact_fn = FFI::Raw−>new(2 'target/release/libembed.dylib'

, 'fact',3 FFI::Raw::int,4 FFI::Raw::int,5 );67 my $fact_val = $fact_fn−>call(30)

;89 say "Factorial [$fact_val]";

Сохраняем, запускаем:1 alpha6$ perl ./main.pl2 Factorial [1409286144]

Page 61: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

3 Perl code done!

Хм, кажется, что-то пошло не так…

В этом примере можно увидеть наглядноразличия Perl и языков более низкогоуровня. Если посмотреть на результатработы функции, то видно что факториал30 немножко не является факториалом 30,хотя бы потому что в нем должно быть 22цифры. При этом просто увеличение раз-рядности до u64 не поможет, потому чтотуда он тоже не влезает. В общем, моральсей басни такова — следите за перепол-нением переменных, так как компиляторэтого не отслеживает, и рантайм-проверокпо умолчанию тоже нет.

Впрочем, при изменении разрядности с intдо int64, факториал 14 рассчитывается вер-но, если верить калькулятору, а все, что вы-

Page 62: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

ше 15 — это уже математика с хитрыми ал-горитмами, Rust из коробки с ней работатьне умеет.

Еще одна проблема — FFI::Raw не позво-ляет напрямую передавать и возвращать извнешнего кода что-то сложнее примитив-ных типов. То есть передать вфункциюхешили вернуть вектор не получится. Но все-гда можно работать со структурами С, а пе-регнать Perl-структуру в сишную — задачаэлементарная.

Приведем наш lib.rs к виду:1 pub struct Args {2 init: u32,3 by: u32,4 }56 #[no_mangle]7 pub extern fn use_struct(args: &

Page 63: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Args) −> u32 {8 println!("Args: {} − {}",

args.init, args.by);9

10 return args.init;11 }

Здесь мы объявляем структуру Args и дела-ем ее доступной снаружи нашей библиоте-ки указанием pub. В функции use_structмы говорим компилятору, что ожидаем навходе указатель на эту структуру. Ну и воз-вращаем обратно первый элемент структу-ры.

В перловый код вставим такое:1 my $packed = pack('LL', 42, 21);2 my $arg = FFI::Raw::MemPtr−>

new_from_buf($packed, length$packed);

3

Page 64: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

4 my $foo = FFI::Raw−>new(5 $shared, 'test_struct',6 FFI::Raw::uint,7 FFI::Raw::ptr,8 );9

10 my $val = $foo−>($arg); #Получаемструктуру из Rust кода

11 say "result [$val]";

Здесь мы упаковываем данные для струк-туры (два числа int32), затем создаем изних объект FFI::Raw::MemPtr, которыйвыделяет область памяти и укладываеттуда упакованную стуктуру. Затем мыпривязываемся к функции test_structиз нашей библиотеки и говорим, что будемпередавать в нее указатель.

Соберем и запустим:1 alpha6$ cargo build −−release

Page 65: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

2 alpha6$ perl ./main.pl3 Args: 42 − 214 result [42]

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

Создадим счетчик (действие не особоосмысленное, зато показывает как с этимвсем работать). Приведем наш lib.rs квиду:1 #![allow(non_snake_case)]2 use std::mem::transmute;34 pub struct Args {5 init: u32,6 by: u32,7 }8

Page 66: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

9 pub struct Counter {10 val: u32,11 by: u32,12 }1314 impl Counter {15 pub fn new(args: &Args) −>

Counter {16 Counter{17 val: args.init,18 by: args.by,19 }20 }2122 pub fn get(&self) −> u32 {23 self.val24 }2526 pub fn incr(&mut self) −> u32

{27 self.val += self.by;28 self.val29 }

Page 67: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

3031 pub fn decr(&mut self) −> u32

{32 self.val −= self.by;33 self.val34 }35 }3637 #[no_mangle]38 pub extern fn createCounter(args:

&Args) −> *mut Counter {39 let _counter = unsafe {

transmute(Box::new(Counter::new(args))) };

40 _counter41 }4243 #[no_mangle]44 pub extern fn getCounterValue(ptr

: *mut Counter) −> u32 {45 let mut _counter = unsafe { &

mut *ptr };46 let val = _counter.get();

Page 68: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

47 return val;48 }4950 #[no_mangle]51 pub extern fn incrementCounterBy(

ptr: *mut Counter) −> u32 {52 let mut _counter = unsafe { &

mut *ptr };53 _counter.incr()54 }5556 #[no_mangle]57 pub extern fn decrementCounterBy(

ptr: *mut Counter) −> u32 {58 let mut _counter = unsafe { &

mut *ptr };59 _counter.decr()60 }6162 #[no_mangle]63 pub extern fn destroyCounter(ptr:

*mut Counter) {64 let _counter: Box<Counter> =

Page 69: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

unsafe{ transmute(ptr) };65 // Drop66 }

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

Что здесь происходит? Сначала создаютсядве структуры данных: Args и Counter. Вцелом они одинаковые, но для Counterмысоздаем реализацию, которая добавляет на-бор методов к нашей структуре.

Затем мы объявляем публичную функциюcreateCounter, которая на вход прини-мает указатель на структуру данных Args.Из этой структуры мы создаем объект

Page 70: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Counter, который упаковываем в контей-нер Box::new, который будет доступенчерез указатель. Работа с transmute делоопасное, поэтому мы оборачиваем созда-ние контейнера в unsafe и этим самыммы говорим компилятору, что мы самипозаботимся о проверке на безопасностьвсей этой конструкции (чего мы не делаемв данном случае).

После создания контейнера мы возвраща-ем из функции изменяемый указатель, с ко-торым и будем дальше работать везде.

Теперь создадим файл counter.pl, ко-торый будет использовать нашу новуюбиблиотеку:1 #!/usr/bin/env perl23 use v5.16;4 use FFI::Raw;

Page 71: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

56 my $shared = 'target/release/

libembed.dylib';78 my $packed = pack('LL', 42, 21);9 my $arg = FFI::Raw::MemPtr−>

new_from_buf($packed, length$packed);

1011 my $createCounter = FFI::Raw−>new

(12 $shared, 'createCounter',13 FFI::Raw::ptr, FFI::Raw::ptr14 );1516 my $getCounterValue = FFI::Raw−>

new(17 $shared, 'getCounterValue',18 FFI::Raw::uint, FFI::Raw::ptr19 );2021 my $incrementCounterBy = FFI::Raw

−>new(

Page 72: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

22 $shared, 'incrementCounterBy',23 FFI::Raw::uint, FFI::Raw::ptr24 );2526 my $ptr = $createCounter−>($arg);2728 my $val = $getCounterValue−>($ptr

);29 say "Current value [$val]";3031 my $nval = $incrementCounterBy−>(

$ptr);32 say "New value [$nval]";

Здесь мы сначала привязываемся к функ-ции createCounter и говорим, что будемпередавать указатель и ждем на выходеуказатель. Затем привязываемся к функ-ции getCounterValue и говорим, чтопередаем ей указатель и ждем unsigned int.Для всех остальных функций должны бытьсозданы аналогичные записи, здесь я их

Page 73: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

описывать не стал.

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

Соберем это все дело и запустим:1 alpha6$ cargo build −−release2 alpha6$ perl ./main.pl3 Current value [42]4 New value [63]

В выводе видно, что мы получили текущеезначение счетчика после создания, а потомизменили его значение.

Теперь мы умеем получать структру изRust и передавать ее обратно в библиоте-

Page 74: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Но структуры-то получать хочется! Что ж,пришло время добавить еще один слой аб-стракции—используем FFI::Platypus вместоFFI::Raw.

FFI::Platypus является намного более су-ровыминструментомипредоставляет кучуопций, позволяя не заморачиваться с низ-коуровневой работой с данными в отличиеот FFI::Raw.

Проверим, что у нас все работает как

Page 75: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

надо. Установим FFI::Platypus и FFI::Platypus::Lang::Rust, этот модульпозволяет использовать при объявленияхструктур и функций структуры из Rust, ане запоминать маппинг между Rust и C.

Изменим lib.rs и создадим файл plat.pl с содержимым, указанным ниже.

src/lib.rs:1 #[no_mangle]2 pub extern fn hello_plat(arg: u32

) {3 println!("Hello PL {}", arg);4 }

plat.pl:1 #!/usr/bin/env perl2 use v5.16;3 use FFI::Platypus;4

Page 76: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

5 my $shared = 'target/release/libembed.dylib';

67 my $ffi = FFI::Platypus−>new();89 $ffi−>lib($shared);

10 $ffi−>lang('Rust');11 $ffi−>attach( hello_plat => ['u32

'] => 'void' );12 hello_plat(1);

Здесь мы создаем объект FFI::Platypusи указываем ему путь к библиотеке —$ffi−>lib($shared), затем указываем,какой язык мы хотим использовать $ffi−>lang('Rust'). После этого указанияFFI сам подгрузит модуль FFI::Paltypus::Lang::<LangName>, и можно будетиспользовать фичи для конкретного языка(соответствующий модуль должен бытьпредварительно установлен).

Page 77: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Далее мы добавляем функцию из библио-теки в перловый код, конструкция $ffi−>attach создает функцию с указаннымименем, которая транслирует данные в/изсоответстующую библиотечную функцию.Функция создается в пространстве именмодуля, так что надо следить, чтобы небыло перекрытия функций из библиотекии текущего пакета.

Собираем, запускаем:1 alpha6$ cargo build −−release2 alpha6$ perl ./plat.pl3 Hello PL 1

Все работает как и задумано.

Настало время получить желанную струк-туру из нашей библиотеки.

В очередной раз переделаем наш src/lib

Page 78: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

.rs:1 use std::mem::transmute;23 pub struct Args {4 init: u32,5 by: u32,6 descr: String,7 }89 impl Args {

10 pub fn new(init: u32, by:u32, descr: String) −>Args {

11 Args{12 init: init,13 by: by,14 descr: descr,15 }16 }17 }1819 #[no_mangle]

Page 79: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

20 pub extern fn get_struct() −> *mut Args {

21 let my_struct = unsafe {transmute(Box::new(Args::new(42, 1, "hi from Rust!".to_string()))) };

22 my_struct23 }

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

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

Page 80: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Обратите внимание, как создается объектString, в Rust есть два типа строк — strи String. В чем же отличия между str иString? str это так называемый строко-вый срез. Он имеет фиксированную длинуи неизменяем, поэтому мы не можем ис-пользовать их в структуре (на самом делеможем, но с некоторыми затейливыми те-лодвижениями). Тип String представляетсобой строку, размещаемую в куче и га-рантированно явлющуюся UTF-8 строкой.Обычно String получается из str путемпреобразования через .to_string.

Обратное преобразование осуществляетсячерез & — str = &String.

Более подробно об этом можно почитать вдокументации.

Теперь получим данные из Rust:

Page 81: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

1 use v5.16;2 package My::RustStr;34 use FFI::Platypus::Record;56 # Описываем структуру данных,

которую мы ждем из библиотеки7 record_layout(qw(8 uint rs_counter9 uint rs_by

10 string rs_descr11 ));1213 my $shared = 'target/release/

libembed.dylib';1415 my $ffi = FFI::Platypus−>new;16 $ffi−>lib($shared);17 $ffi−>lang('Rust');1819 # Связываем структуру с нашим

пакетом MyRustStr иприсваиваем ей алиас rstruct

Page 82: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

20 $ffi−>type("record(My::RustStr)"=> 'rstruct');

2122 # Аттачим библиотечную функцию

get_struct в наш пакет23 # и указываем, что ждем от нее

объявленную выше структуру24 $ffi−>attach( get_struct => [] =>

'rstruct', sub {25 my($inner, $class) = @_;26 $inner−>();27 });2829 package main;3031 # Используем наш пакет My::

RustStr для работы сбиблиотекой

32 my $str = My::RustStr−>get_struct;

3334 printf "Struct is [%d][%d][%s]\n"

,

Page 83: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

35 $str−>rs_counter,36 $str−>rs_by,37 $str−>rs_descr;

Сначала мы объявляем пакет My::RustStr, в котором описываем структуру данных,которую мы хотим от нашей библиотеки.Из-за особенностей модуля FFI записьrecord_layout может быть только однана пакет (на самом деле нет, но лучше такне делать), поэтому мы выделяем нашуфункцию в отдельный пакет.

Затем мы создаем новый тип данных в па-кете My::RustStr $ffi−>type("record(My::RustStr)" => 'rstruct'); и назы-ваем его rstruct.

Далее мы, как обычно, создаем биндингдо библиотеки и эспортируем ее в про-странство имен пакета My::RustStr.

Page 84: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Обратите внимание на $ffi−>attach(get_struct => [] => 'rstruct',

sub {, здесь в качестве возвращаемогозначения функции мы указываем, чтохотим получить нашу структуру rstruct.Также мы указываем кастомную функцию-обработчик, передавая coderef последнимаргументом. В данном случае он не де-лает ничего кроме вызова библиотечнойфункции, но туда можно добавить какую-то дополнительную обработку до/послевызова внешней библитеки.

Затем мы просто распечатываем содержи-мое нашей структуры.

Теперь мы также можем передать структу-ру в нашу библиотеку без шаманства с packи указателями. Изменим наш перловыйкод работы со счетчиком.1 use v5.16;

Page 85: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

23 package MyCounter;45 use FFI::Platypus::Record;67 record_layout(qw(8 uint rs_counter9 uint rs_by

10 ));1112 package main;1314 my $shared = 'target/release/

libembed.dylib';1516 my $ffi = FFI::Platypus−>new;17 $ffi−>lib($shared);18 $ffi−>lang('Rust');1920 # Создаем новую структуру данных

с именем CounterStr21 $ffi−>type('record(MyCounter)' =>

'CounterStr');

Page 86: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

2223 # Аттачим функции из библиотеки24 $ffi−>attach(createCounter => ['

CounterStr'] => 'opaque');25 $ffi−>attach(getCounterValue => [

'opaque'] => 'u32');26 $ffi−>attach(incrementCounterBy

=> ['opaque'] => 'u32');2728 # Создаем структуру, из которой

мы создадим счетчик29 my $counter = MyCounter−>new(30 rs_counter => 10,31 rs_by => 2,32 );3334 # Создаем объект счетчика и

используем его для работы35 my $ptr = createCounter($counter)

;36 say getCounterValue($ptr);37 say incrementCounterBy($ptr);

Page 87: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Здесь мы используем opaque в каче-стве возвращаемого значения функцииcreateCounter так как нам нужен сы-рой указатель для работы с остальнымиподключенными функциями. Но при же-лании этот указатель можно превратитьв структуру нужного формата с помощьюфункции cast.

В Rust-коде ничего менять не надо.

Запускаем:1 alpha6$ perl ./plat.pl2 103 12

Итого, мы создали новый объект счетчикаи изменили его.

Теперь мы умеем работать с большейчастью случаев, которые нам могут приго-

Page 88: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

диться при использовании подключаемыхбиблиотек (не только на Rust). Осталосьнаучиться все это автоматически собиратьпри установке перлового модуля.

Для этого нам пригодятся Module::Buildи Module::Build::FFI::Rust.

Приведем структуру проекта к виду:1 Build.PL2 ffi3 lib4 plat.pl

В lib у нас лежат Perl-библиотеки нашегопроекта, в ffi — Rust-исходники. Build.PL выглядит так:1 #!/usr/bin/env/perl23 use strict;4 use Module::Build;

Page 89: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

5 use Module::Build::FFI::Rust;67 my $build = Module::Build::FFI::

Rust−>new(8 module_name => '

MyCounter::Record',9 dist_abstract => 'FFI

test',10 create_makefile_pl => '

traditional',11 dist_author => 'Denis

Fedoseev <[email protected]>',

12 create_readme => '0',13 license => 'perl',14 configure_requires => {15 'Module::Build' => 0.38,16 'File::Which' => 0,17 'Module::Build::FFI' => '0.18

'18 },19 build_requires => {},20 requires => {

Page 90: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

21 'perl' => '5.016000',

22 'FFI::Platypus' => 0,23 'FFI::Platypus::Lang::

Rust' => 0,2425 },26 recommends => {},27 recursive_test_files => 0,28 sign => 0,29 create_readme => 1,30 create_license => 1,31 );3233 $build−>create_build_script;

Обратите внимание на использованиеModule::Build::FFI::Rust вместообычного Module::Build. Запускаемустановку, подготавливаем Build-скрипт:1 alpha6$ perl ./Build.PL2 Can't find dist packages without

Page 91: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

a MANIFEST file3 Run 'Build manifest' to generate

one45 WARNING: Possible missing or

corrupt 'MANIFEST' file.6 Nothing to enter for 'provides'

field in metafile.7 Created MYMETA.yml and MYMETA.

json8 Creating new 'Build' script for '

MyCounter−Record' version 'v0.0.2'

Собираем наши модули:1 alpha6$ ./Build2 cargo build −−release3 Updating registry `https://

github.com/rust−lang/crates.io−index`

4 Compiling winapi v0.2.55 Compiling libc v0.2.4

Page 92: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

6 Compiling winapi−build v0.1.17 Compiling advapi32−sys v0.1.28 Compiling rand v0.3.129 Compiling embed v0.1.0 (file

:///Users/alpha6/projects/tests/build/ffi)

10 Building MyCounter−Record

Устанавливаем:1 alpha6$ ./Build install2 cargo build −−release3 Building MyCounter−Record4 Files found in blib/arch:

installing files in blib/libinto architecture dependentlibrary tree

5 Installing /Users/alpha6/perl5/perlbrew/perls/perl−5.20.3/lib/site_perl/5.20.3/darwin−2level/auto/MyCounter/Record/Record.bundle

6 Installing /Users/alpha6/perl5/

Page 93: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

perlbrew/perls/perl−5.20.3/lib/site_perl/5.20.3/darwin−2level/MyCounter/Record.pm

MyCounter/Record/Record.bundle это иесть наша Rust-библиотека, установленнаяв систему.

Теперь мы умеем работать с Rust-кодомиз Perl и, самое главное, собирать из этогополноценные пакеты, которые и на CPANвыложить можно :)

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

■ Денис Федосеев

Page 94: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

7 Обзор CPAN за ноябрь 2015 г.

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

Статистика

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

Новые модули

HTTP::Cookies::PhantomJS

HTTP::Cookies::PhantomJS — расшире-ние для HTTP::Cookies, которое позволя-

Page 95: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

ет использовать файлы с куками формата,которые применяются в веб-скрапереPhantomJS. Это бывает полезно, когда ку-ки устанавливаются в результате работыjs-кода на стороне клиента при загрузке ре-сурса в PhantomJS, а последующие ресурсыможно загрузить, используя получен-ные куки, с помощью более легковесноговеб-клиента, например, LWP::UserAgent.

GCCJIT

GCCJIT— это обвязка к библиотеке libgccjit,которая позволяет на лету формировать икомпилировать код в машинные инструк-ции.

Page 96: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Locale::TextDomain::OO::Extract::Xslate

Locale::TextDomain::OO::Extract::Xslate позволяет извлекать строки дляперевода из шаблонов Text::Xslate дляпоследующего использования в Locale::TextDomain::OO.

DOM::Tiny

DOM::Tiny — это минималистичныйHTML/XML DOM-парсер с поддержкойCSS-селекторов.1 my $dom = DOM::Tiny−>new(<<EOF);2 <div>3 <p id="a">Test</p>4 <p id="b">123</p>5 </div>6 EOF

Page 97: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

78 say $dom−>at('#b')−>text; # 1239

10 $dom−>find('div p')−>last−>append('<p id="c">456</p>');

1112 say $dom−>at('#c')−>text; # 456

App::remarkpl

App::remarkpl — это утилита, позволяю-щая запустить локальный веб-сервер на ос-нове Mojolicious для отображения презента-ций на основе remark. В качестве парамет-ра указывается путь к файлу с презентациив формате Markdown, после запуска презен-тация может быть открыта в браузере по ад-ресу localhost:3000

Page 98: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Devel::Trepan::Deparse

Devel::Trepan::Deparse — это плагиндля отладчика Devel::Trepan, которыйдобавляет две новые команды: deparse иdeval. Команда deparse позволяет показатькакой код будет выполняться в следующейинструкции, что бывает полезно, когдаотладчик остановился на строке, в которойнесколько операций и не ясно какая из нихбудет выполняться на следующем шаге:1 if ( grep { $_ eq 'foo' } @bar )

{...}

выражение внутри if или уже блок кодаgrep для какого-то текущего значения@bar? Команда deparse покажет какаяименно операция будет выполнятьсяследующей:1 : deparse

Page 99: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

2 # code to be run next...3 $_4 # contained in...5 $_ eq 'foo'

Mail::DKIM::Iterator

Модуль Mail::DKIM::Iterator позволя-ет организовать проверку DKIM-записейв почтовых сообщениях и добавлятьDKIM-подпись к ним. Основное отличиеот Mail::DKIM — это возможность орга-низовать неблокирующуюся потоковуюобработку писем.

Page 100: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Unix::Pledge

Недавно появившийся в OpenBSD систем-ный вызов pledge(2) теперь можно исполь-зовать в perl-программах, которые будут ра-ботать на этой платформе, с помощью мо-дуля Unix::Pledge. Модуль позволяет на-ложить ограничения на процесс, например,запретить чтение или запись файлов, с ука-занием списка файлов-исключений.

Perl6::Export

Perl6::Export реализует Perl 6 рольis export для Perl 5 модулей, позволяяизящно экспортировать функции модуля.Например, сравнение с Exporter:1 package My::Module; |

package My::Module;

Page 101: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

2 use Exporter; |use Perl6::Export;

3 |4 our @EXPORT = qw(foo bar); |

sub foo is export(:MANDATORY);5 |

sub

bar

is

export(:MANDATORY);

6 |7 our @EXPORT_OK = qw(baz); |

sub baz is export(:DEFAULT :qux);

8 our %EXPORT_TAGS = |9 qw(qux => [qw(baz)]); |

Page 102: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Pg::Reindex

Индексы Postgresql должны периодическипересоздаваться для достижения опти-мальной производительности. Например,это можно сделать с помощью командыREINDEX, но в этом случае потребуетсяэксклюзивная блокировка всей таблицы.

Модуль Pg::Reindex выполняет созданиеиндекса с помощью CREATE INDEXCONCURRENTLY, который может выпол-няться без блокировки. Затем он начинаеттранзакцию, в которой удаляет старыйиндекс и переименовывает новый. Такимобразом достигается пересоздание индексабез длительной блокировки.

Page 103: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Sereal 3.010

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

JSON::Validator 0.63

Модуль JSON::Validator позволяет про-водить проверку данных в формате JSONна соответствие JSON-схеме. В новой вер-сии удалена поддержка использованиямодулей YAML и YAML::Tiny для загрузки

Page 104: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

JSON-схемы в формате yaml (поддержи-ваются только YAML::XS и YAML::Syck).Связано это с тем, что YAML и YAML::Tiny в некоторых случаях некорректновыполняют разбор формата yaml.

PathTools 3.60

Вышло обновление дистрибутива PathTools,включающий модули для работы с путямина различных поддерживаемых в Perl плат-формах. В новой версии включён модульFile::Spec::AmigaOS для поддержкиплатформы AmigaOS.

Page 105: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

MIME-Types 2.12

В новой версии дистрибутива MIME−Typesобновлена база данных MIME-типов, в со-ответствии с текущим состоянием в IANA.Требования к версии Perl снижены до 5.6.

utf8::all 0.017

Прагма utf8::all тотально включает UTF-8: для исходного кода программы, переко-дирует открываемые файлы и аргументы,переданные в командной строке, разреша-ет использование последовательностей \N{...} для задания юникод-символов по ихимени и т.д. В новой версии появилась воз-можность отключать эффект прагмы, с по-мощью no utf8::all.

Page 106: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

PDL 2.015

Вышел новый релиз PDL — модуля для ра-боты научных вычислений и отображенияданных. Как указано в журнале изменений— это отполированный релиз с исправлени-ем всех замечаний обнаруженных в преды-дущей версии с улучшенной поддержкой64-битных целых.

perl 5.23.5

Вышла новая версия Perl 5.23.5 для раз-работчиков. В новом релизе проведенаоптимизация, которая ускорила выпол-нение арифметических операций, такихкак сложение, вычитание и умножение.Кроме того, теперь быстрее стали работатьоперации ++ и −−. Исправлено несколь-

Page 107: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

ко ошибок с крахом интерпретатора,например, в функции pack: perl −e 'pack "WH200000", \0'

App::perlbrew 0.74

Обновился менеджер Perl-инсталляцийperlbrew. В новой версии появиласьподдержка переменной окруженияPERLBREW_LIB_PREFIX, которая позво-ляет добавить каталог с библиотеками,имеющей приоритет над локальнымикаталогами библиотек perlbrew (т.е. ./lib:$PERL5LIB). Теперь при загрузкефайлов будет отдаваться предпочтениеhttps-ресурсам и обязательно проверятьсяих сертификат.

Page 108: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

podlators 4.00

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

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

Page 109: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

8 Интервью с Дмитрием Шаматриным

Дмитрий Шаматрин — программист,с недавнего времени организатор Perl-конференций

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

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

Хорошо помню, что Паскаль мне тогдаочень не понравился. Но серьезно при-годилось программирование в процессенаписания диплома в универе. Если кто нев курсе, по образованию я химик.

Так вот, есть такой большой и страшныйаппарат — масс-спектрометр. Он определя-

Page 110: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

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

Emacs. Если/когда нет emacs, могу ис-пользовать vim. Тут уже дело привычки.Так сложилось, в основном, исторически.Долгое время под языки, с которыми яработаю, не было вменяемых IDE. А потомуже просто привык, и еще раз переучивать-

Page 111: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

ся ради сиюминутного профита смысладля себя не вижу.

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

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

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

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

Page 112: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

Erlang, Haskell, Lua.

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

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

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

• Быстрая разработка.• Вменяемое событийное программи-рование.

• Ссылочная механика.• Здравая и продуманная системамодулей/библиотек.

• Простота создания своих модулей(привет ExtUtils::MakeMaker).

Page 113: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

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

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

Отличный язык. Жаль, что невовремя.

Было бы приятно, если бы взлетело, но я не

Page 114: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Что лучше: работать на аутсорс или напродукт?

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

Как жить программисту, если кажется,

Page 115: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

что вокруг одни дураки?

Понять и простить. Правило 95% непобеди-мо.

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

Лучше специализация или везде по чуть-чуть?

Page 116: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

Так все-таки Erlang или Haskell?

Они решают примерно подобные задачи.

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

Page 117: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

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

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

Page 118: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

и сложная система типов поначалу будетсильно взрывать мозг. Мой совет — учитеоба :D Потому как понимание хаскеля,как чистого функционального языка, вконечном итоге, позволяет намного лучшеписать на эрланге.

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

Когда как. Обычно несколько часов в день.

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

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

Page 119: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

К тому же, культуры программирования,как таковой, тоже, в широких массах, особоне было. Соответственно, весь тот код, закоторые клеймят Perl, это не вина языка.Если бы в то же время появился, например,питон или руби, сейчас бы слава worn-языка была бы у одного из них. Просто нев то время. Почему стоит учить? Да пото-му, что он достаточно низкоуровневый,чтобы разобраться, как работают файловыедескрипторы, сокеты, счетчик ссылок. Ион достаточно высокоуровневый, чтобыразобраться с концепциями в мире совре-менного программирования. Ну и имееточень большую базу библиотек, да.

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

Будут еще хакатоны и конференции?

Будут и много. Скорее всего что-то про-

Page 120: PragmaticPerl34pragmaticperl.com/issues/34/pragmaticperl-34-ebook.pdf · http/2 и никакой альтернативы для его ... доклады. Надо сказать,

ведем летом. Есть в планах одесскаяконференция по функциональному про-граммированию.

Какой веб-фреймворк сейчас стоит ис-пользовать и почему?

Мне в последнее время очень нравитсяперловый Catalyst. Почему? Удобный, мно-го умеет, под него написано очень многомодулей. Ну и еще очень немаловаж-ный момент — адекватный мейнтейнер.Минусы — громоздкий.

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