平常運転

アニソンが好き

過去記事とかは記事一覧で見れます

Perl 6 のモジュールエコシステムの話とモジュールを公開する話 (2016年12月版)

このエントリは はてなエンジニアアドベントカレンダー2016の13日目のエントリです。12日目のエントリは追って書かれる見込みです。
それぞれ力のこもったエントリが並んでいるところ恐縮ですが、 Perl 6 の話をカジュアルにしようと思います。そして、この話は先日 YAPC::Hokkaido で LT した "Publishing a Perl6 Module" を revise の上ブログエントリにしたためた物でもあります。

www.slideshare.net

このエントリを読むことで Perl 6 のモジュールエコシステムについて雰囲気を感じてもらったり、あわよくばちょっと面白そうだから Perl 6 のモジュールを書いてみるかと思ってもらえれば幸いです。一方で、 Perl 6 のコードの書き方のような話はほぼしないので、その辺は一般的な Perl 6 入門的なドキュメントを探していただければと思います。
なお、前述したようにこのエントリは"はてなエンジニアアドベントカレンダー2016"の一部ではありますが、 Perl 6 は特にはてなの中で利用されているわけではなく、このエントリは id:astj の完全な趣味によって書かれています。

Perl 6

YAPC だと端折ったのですが、いちおう Perl 6 とは、という話をしておきます。 Perl 6 は Perl 5 (一般に Perl と呼ばれるのはこっち)を土台として設計されたプログラミング言語で、ソースコードや言語仕様そのものには Perl 5 との互換はありません。静的型付けが可能になり(!)、言語レベルでオブジェクト指向がよくサポートされる、並行・非同期プログラミングがサポートされるなど、 Perl 5 と比較して様々な点で強化された言語です。
2015年のクリスマスに "Production Ready" としてリリースされたことが一部で話題になりましたが、速度面や安定性などでは Perl 5 や他の主要なプログラミング言語と比べればまだまだ、というのが正直なところです。
Day 24 – An Unexpectedly Long-expected Partyperl6advent.wordpress.com

とはいえ、Perl 6 の主要実装である Rakudo と MoarVM は進化し続けており、(僕は過去における事情はあまり知らないのですが)過去に言われていた状況と比べて速度面や安定性は向上しています。
個人的には Perl 5 の系譜を感じられつつも進化した言語仕様は興味深く、触り甲斐のある言語だというように思っています。

Perl 6 におけるモジュールエコシステム

Perl 5 や他の言語にあるようなモジュール/ライブラリ機構は、もちろん Perl 6 にも導入されています。 まあこの辺は僕がうだうだ書くより公式のドキュメントを見てもらう方が手っ取り早いです。合間に出てくるサンプルコードだけでも雰囲気が分かるはず。

Modules

モジュールがあるということは、それを導入する為の仕組みもまた存在します。 Perl 6 におけるいわゆるパッケージマネージャとしては、panda がよく知られているほか、 zef というものもあります。これらはローカルのファイルシステムからモジュールをインストールできるほか、 git リポジトリを指定してのインストールを行うことも出来ます。

$ panda install ./
$ zef install git://github.com/ugexe/zef.git

しかし、モジュール/ライブラリ機構として、特に Perl 5 との類推で想像されるのは、モジュールを中央管理する CPAN のような仕組みでしょう。 Perl 6 においても CPAN を利用したエコシステムは検討されているところですが、今のところ、 GitHub からのインストールを前提としてメタデータを管理する機構が用意されており、今のところはその仕組みを用いてインストールすることになります。

Perl 6 Modules Directory

$ panda install SQL::NamedPlaceholder

さて、(CPAN を使うにせよ現行のエコシステムを使うにせよ)、モジュールをインストール仕組みがあるということは、モジュールの依存関係などを記録するメタ情報が存在します。言語仕様によってドキュメントされており、S22 に記載があります。

{
  "authors" : [
    "astj"
  ],
  "build-depends" : [ ],
  "depends" : [ ],
  "description" : "extension of placeholder",
  "name" : "SQL::NamedPlaceholder",
  "perl" : "6",
  "provides" : {
    "SQL::NamedPlaceholder" : "lib/SQL/NamedPlaceholder.pm6"
  },
  "resources" : [ ],
  "source-url" : "git://github.com/astj/p6-SQL-NamedPlaceholder.git",
  "test-depends" : [
    "Test::META"
  ],
  "version" : "0.1.0"
}

リポジトリ直下の META6.json 、あるいは META.info にこのようなメタデータを記載することで、モジュールの依存管理を行う仕組みとなっています。現状のエコシステムにおいては、 GitHub 上の perl6/ecosystem リポジトリに各リポジトリのメタ情報ファイルの URL を書き並べ、その情報を収集したメタデータ API が機能しています。

github.com

メタデータ APIについてはしばらく前にエントリを書いています。気になる方はこちらをご覧下さい。

astj.hatenablog.com

Perl 6 でモジュールを作って公開する

さて本題。 Perl 6 のモジュールについては様々な物が公開されており、特に Web アプリケーションの開発に必要なモジュールなどは一通り提供されていますが、他の言語と比べて絶対数が少ないのも事実です。そのため、 Perl 6 での開発を行っていると既存のモジュールでは物足りずに自分でモジュールを実装することも度々ありますが、(2016/12時点では)エコシステムが簡便なこともあり、簡単に自作したモジュールをエコシステム下で公開することが可能です。
前述したように、(2016/12時点の仕組みにおいて) Perl6 のモジュールを公開するためには、以下のステップを踏めばよいです。

リポジトリを作る / ディレクトリ構造に配置する

リポジトリそのものはふつうに GitHub 上でリポジトリを作って git clone をすればよいです。
ディレクトリ構造やメタデータの管理について、Perl 5 ではMinillaなどのツールがありましたが、 Perl 6 の場合はMi6 を使うのが扱いやすいように思います。

$ panda install App::Mi6
$ mi6 start SQL::NamedPlaceholder
Successfully created SQL-NamedPlaceholder

コードやドキュメントを書く

コードは書けばよいので書きましょう。テストの実行にも Mi6 を使うと便利です。

$ mi6 test

また、 Mi6 は mi6 build によって Pod から README の markdown を生成するので、ドキュメントについてもモジュール内部に Pod 形式で記述します。なんか Perl 5 の Pod と異なる挙動の箇所もある気がするので、適宜確かめながら書くとよい気がしています。

$ perl6 --doc lib/SQL/NamedPlaceholder.pm6 # プレーンテキストが出力される
$ mi6 build # README.md が更新される

そして勿論メタデータへも記述が必要です。リポジトリが提供するモジュールや、依存モジュールについてを META6.json に記載します。
このメタデータの妥当性が気になるところですが、これはTest::METAというモジュールを使ってテストコードを記述しておくのがお勧めです。 Test::META の README にあるようなテストコードを書いておくとテストできます。

$ TEST_AUTHOR=1 mi6 test -v t/99-meta.t
==> Set PERL6LIB=/Users/asato/.ghq/github.com/astj/p6-SQL-NamedPlaceholder/lib
==> prove -e /Users/asato/.rakudobrew/bin/../moar-blead-nom/install/bin/perl6 -r -v t/99-meta.t
t/99-meta.t ..
1..1
    ok 1 - have a META file
    ok 2 - META parses okay
    ok 3 - have all required entries
    ok 4 - 'provides' looks sane
    ok 5 - Optional 'authors' and not 'author'
    ok 6 - name has a hypen rather than '::' (if this is intentional please pass :relaxed-name to meta-ok)
    ok 7 - no 'v' in version strings (meta6 version greater than 0)
    1..7
ok 1 - Project META file is good
ok
All tests successful.
Files=1, Tests=1,  0 wallclock secs ( 0.02 usr  0.00 sys +  0.26 cusr  0.04 csys =  0.32 CPU)
Result: PASS

モジュールの挙動を確かめる

ここまでできて、きちんと各種構成が出来ていれば後は ecosystem に登録するだけでよいのですが、実際に正しくインストールできるリポジトリかどうかは事前に確かめておきたいところです。前述のように Perl 6 のモジュールマネージャはローカルのファイルシステムや git リポジトリからもインストール出来るため、それらからのインストール(やアンインストール)ができることを確かめておくと安心です。

$ panda install .
$ panda install git://github.com/YOU/Module.git

ecosystem に追加する

GitHubリポジトリが公開され、 git 経由でモジュールがインストールできることを確認したらば、後は ecosystem に追加することになります。perl6/ecosystem リポジトリを fork し、 META.list に書き足して Pull request を送ります。Pull request は freenode の #perl6 チャンネルに通知されることから、特に問題なければ数時間程度でマージされ、その後しばらくすると panda installなどのコマンドでインストールできることになります。つまりリリース完了です。
筆者が SQL::NamedPlaceholder を追加したときの Pull request がこちらです。
github.com

備考: モジュールのアップデート

ecosystem の META.list に記載するのはあくまでメタデータファイルの所在なので、バージョン情報などは ecosystem リポジトリには含まれていません。そのため、(現行のエコシステムでは)モジュールのアップデートは自分のリポジトリの master ブランチを更新するだけで行われます(必要に応じてメタデータのバージョン情報は更新しておきたいですね)。

結び

Perl 6 のモジュールエコシステムと、そのエコシステムに則ってモジュールを公開する話についてここまで記述しました。 Perl 6 は言語的になかなか面白い言語なので、興味を持って触れていただければ幸いです。
また、perl6/perl6-most-wantedリポジトリでは、"most-wanted pure Perl 6 modules" の一覧も公開されており、ここにあるモジュールの公開は特に歓迎されるということで、ネタ元としてはお勧めです。
github.com