あと味

たくさん情報を食べて、たくさん発信すると、あとになって味わい深い。

春のJAWS-UG 三都物語 2013でMTに関するLTしました

AWSを使ったこと、ほぼなかったんですけど、これをキッカケにして、今後は活用するようになりそうです。

発表内容をシェアするとともに、ちょっと考えることを書きます。5分という短い時間でしたが、伝えたいことは伝えられたんじゃないかと思います。

思ったこと

Wordpress界隈に比べて、MT界隈のAWSのノウハウは、ウェブを見る限りではまだ少ないように思います。

特に、Movable Typeは静的ファイル出力が前提のソフトウェアなので、S3やCloudFrontがもっと活用されるようになるといいなと思いますし、自分は今後活用しようと思います。

また、スライドの中では、管理画面なくてもいいじゃんみたいな話をしていますが、これは極端な話だったかもしれません。しかし、MTはPerlで書かれたソフトウェアなので、コマンドラインツールとの親和性は実際高いと思っています。CPANもあるし。

コードベースでMTを操作すること

ネタに走ってしまって、多分あまり伝わってないので、コードベースでMTを操作するということについては、本エントリでもう少し掘り下げることにします。

MT::Toolクラスのサブクラスを作れば簡単にコマンドラインツールを作ることができます。*1

管理画面経由にせよ、コマンドラインツール経由にせよ、使うのはMTのアーキテクチャです。MTのアーキテクチャは、管理画面に特化しているわけではなく、コードから利用することも可能です。コードから利用するのはWordpressより扱いやすいように思います。Perl製のソフトウェアということもありますが、こういう点がMovable Typeの方が弄っていて楽しいと思う理由なんだと思います。

MTは、ライブラリを直接useして利用できる作りにもなっています。*2

プラグインかtoolsスクリプトかの違いは、MTのオペレーションツールがブラウザかターミナルかの違いだけです。
自分は、コマンドラインツールが好きなので、今後、MTのコマンドラインツールをいろいろ作ることでしょう。コマンドラインツールをしっかり作ってしまえば、どうしても管理画面上から利用したい時には、ブラウザ用のインターフェイスを追加するだけで済むはずです。たぶん。

ついでなので、作りかけで途中になっていた、MTObjectImporterというプラグインをgithubに上げました。YAMLで記事をインポートしたいなと思って作り始めたら、JSONも構造にてるし、EntryとPageも構造似てるしってことになって、ひとつメタなプラグインにしました。

大したことは書いてありませんが、ライブラリをuseして利用できることを意識して作ってあります。こんな感じで、今後もまずはコマンドラインツール、必要に応じてブラウザ用のインターフェイスを用意する、みたいな感じで作ろうと思ってます。テストもしやすいですし。

まとめ

今後、MTらしさを生かしつつAWSを活用したいですね。

*1:perldoc MT::Toolしましょう

*2:githubのmovabletypeのtディレクトリを見よ

俺、今大阪におんねん

ごめんなさい、本当は関西弁まったく使えません。

昨年末から、アルファサード株式会社で働いています。今は主に製品サポートと製品開発を担当しています。

大阪勤務なので、大阪に引越しまして、今や大阪府民です。

これまでも、福井から関西の勉強会に参加することがありましたが、より参加しやすくなりますし、関西圏の方、仲良くしてください。

先日、Movable TypeのextlibディレクトリのCPANモジュールカタログ - あと味という記事の最後の方に、「来年はMovable Typeに本気で取り組みます。」と書いておりましたが、アルファサードPowerCMSというMovable Typeを拡張したCMSを開発している会社なので、嘘偽りなく、今年からはMTに本気で取り組むことになります。

Perlで仕事をしたいと思いつつ、Web制作で関わり弄ってて楽しかったMTと戯れながら、いちひよっこPerlプログラマとして頑張っていきたいと思う所存です。

今後はMTの記事やPerlの記事が増えることと思いますが、個人のライフワークとして、特に関数型言語には興味を持ち続けると思うので、そういう記事も継続的に書いて行きたいと思います。

ちょっとフロントエンドから離れた感はあるのはありますが、未だ興味の対象としては大きな要素なので、今後も勉強していこうと思います。

ということで近況報告でした。

サクッとPSGIなMTOSの開発環境を用意する方法

MTは5.2.2からPSGI対応したということで、今までPSGIアプリケーションをMojoliciousやMENTAで作ることもあった自分としては、かなり嬉しい出来事でした。

Mojoliciousなどは、開発用のPSGIサーバーも同梱されていて、ポータブルだし、サクッと開発環境を用意して、プログラム書き始めることができるのがとても良いですね。

どのCMSApacheの設定から始めて、DB作って、それらの開発環境を外に持っていく時も同じようなことをして云々かんぬんというのに辟易していました。Cartonなどを利用すれば、Perlの実行環境を除いて、アプリケーションディレクトリ配下にアプリケーションが動作するすべての条件を含めることができるのが快適で快適で。

これとなるべく近いことをMTOSでやってみようという試みです。基本的にPSGIで動かす話なので、CGIで動かす場合は、今までどおりメンドイですね。

MTOSを取得する

MTOSはGithubで公開されているので、とても助かります。

$ cd /path/to/yoursite
$ git clone https://github.com/movabletype/movabletype.git mt

これで取得完了です。特定のbranchや特定のtagのファイルが必要な場合は、以下のコマンドも適宜実行しましょう。

$ cd mt
$ git tag -l
$ git checkout -b mt5.2.3 origin/mt5.2.3

とか、

$ git branch -r
$ git checkout -b develop origin/develop

とか。

以降、すべての操作をmtディレクトリの中で行うので、cdコマンドは省略します。

最後にmakeします。

$ make me

シェバンを書き換える

すべての.cgiのシェバンが、/usr/bin/perlになってますが、自分の開発環境で、そのPerl使うことは皆無ですし、CPANモジュールもまったく追加してないので、シェバンはワンライナーで書き換えます。

$ find . -name '*.cgi' -or -name '*.t' -o -name '*.pl' -o -name '*.psgi' | xargs grep -lE '^#!/usr/bin/perl' | xargs perl -p -i -e 's|^#!/usr/bin/perl(\s*(?:-w)?)$|#!/usr/bin/env perl$1|'

DBを作成する

これもSQLiteでできればなー・・・。という感じ。他はすべてアプリケーションのディレクトリに閉じ込めることができますが、ここばかりはどうにもなりませんね。

MySQLの設定 : Movable Type 5 ドキュメント

この辺は、今後、コマンドラインスクリプトで自動化しようと思います。

ディレクトリの配置

こんな感じにするのが良いと思います。

www (プロジェクトのルート)
├─ mt (MTのCGIPath)
├─ mt-static (MTのStaticPath)
└─ public (公開領域)

以下、このディレクトリの配置を前提に、設定ファイルにパスを書いています。

mt-config.cgiを用意する

最小限のmt-config.cgiは以下のような感じになりました。

CGIPath /mt/
StaticWebPath /mt-static
StaticFilePath /path/to/mt-static
ObjectDriver DBI::mysql
Database database
DBUser dbuser
DBPassword dbpassword
DBHost localhost
DefaultLanguage ja

/mt/foo.cgiが、それぞれ別個のPSGIアプリケーションになります。MTの管理画面は、/mt/mt.cgiです。

app.psgiを用意する

mt.psgiというものがあるのですが、書き換えたいのと、plackupでファイル名指定するのが面倒なので、mtディレクトリ配下にapp.psgiを用意します。ちなみに、コレが今回の肝です。

use strict;
use warnings;
 
use lib qw(lib);
 
use MT::PSGI;
use Plack::Builder;
 
builder {
    enable 'DirIndex',
        dir_index => 'index.html';
    enable 'Static',
        path => qr{^/(?:(?!mt/|mt-static/))},
        root => '/path/to/public';
    MT::PSGI->new()->to_app;
};

Plackミドルウェアを2つ使っています。mt.psgiは個別のPSGIアプリケーションを包括した大きなPSGIアプリケーションになっていて、中でMT標準のアプリケーションやら、プラグインで利用するアプリケーションやらをPSGIアプリケーションにして、マウントしてみたいな処理をしています。

外から、mt.psgiを拡張しようとすると、今のところ、Plackミドルウェアしかないのかなーと思っています。

とは言え、既存のPlackミドルウェアの資産が活用できるのは魅力です。
もしかしたら、今後、MTのプラグインだけではなく、mt.psgi用のPlackミドルウェアもいろいろ出てくるのかもしれませんね。

静的ファイルを配信するためだけに、Apacheを設定するのは流石にだるいので、PSGIサーバーさん(plackup)に、そこんとこも頼むことにします。

静的コンテンツを配信するミドルウェアであるPlack::Middleware::Staticと、特定のファイル名をApacheのDirectoryIndexのように設定できるPlack::Middleware::DirIndexを利用しています。

Plack::Middleware::DirIndexの方は、Plack::Middleware::Staticの正規表現をもうちょっと書いたら不要かもしれません。もしくは、インラインでミドルウェアを書くとか。

ちなみに、Plack::Middlewara::DirIndexの存在は、Plackのgithub上にあったIssueで知りました。

MTOSの起動

plackup

以上!

デフォルトでは、ポートが5000番で起動するので、http://localhost:5000/mt/mt.cgiがMTの管理画面、http://localhost:5000/がサイトルートになります。

まとめ

以上で、割とポータブルで、サクッと用意できるMTOSの開発環境が用意できたと思います。用意が楽な上に、今までより速いです。

一応、公式では、plackupの制約上、PSGIサーバーはStarmanの利用が想定されていて、plackupはあくまで開発用と割り切って使いましょう。プラグイン入れた時とかアップグレード後とか何かと再起動必要だし。

初期状態では、CPANモジュールがいろいろ足らないと思いますが、この辺の依存関係を書いたMakefile.PLを用意して、Cartonで管理するのが良いと思います。

公開サーバーにMTを置かないという選択肢があるなら、これだけでも、高機能な静的HTML生成器になるし、汎用的なテキストファイル生成機になりますね。

プログラミングHaskellのfoldr, foldlの説明が秀逸だった件

今年はHaskellを勉強しています。

土日などを利用して、すごいH本を3〜4週間かけて読み終えました。時間かかった分、記憶の密度が低くて、まだ理解度は低いです。

新しい概念を学ぶ時は、同じテーマの本を何冊か読んで、本当に読みたかった本を再度読み直すというのが自分の学習の方法として定着しているので、今は、プログラミングHaskellを読み進めています。

すでに「ふつうのHaskellプログラミング」は読み終えていましたが、改めて読むと、本当に普通のプログラミング本に感じたので、すごいH本がかなり刺激的で、よくできた本なんだと思います。読み直す時が楽しみであります。

本題

さて、「プログラミングHaskell」の話に戻りますが、foldrとfoldlの説明の箇所が秀逸だと思ったので内容を紹介してみます。*1

fold関数は、他の言語でreduceとかinjectとか呼ばれている関数ですね。個人的には、かなり表現力が強い関数なので、一番好きな関数かもしれません。*2

プログラミングHaskellでは、冒頭にこんな紹介があります。

引数にリストを取る関数は、リストに対する再帰を使って、以下のような簡単な様式で定義できることが多い。

f [] = v
f (x:xs) = x f xs

標準ライブラリで提供される高階関数foldr(fold rightの略称)は、この再帰的な様式を抽出する。演算子と値vは引数となる。

なんのこっちゃという感じですが、確かに、fold関数には引数にリストを除いて、に相当する関数と初期値に相当する値vを渡します。

例にある、sum関数とproduct関数のfoldを使わない定義はこんな感じです。

sum []         = 0
sum (x:xs)     = x + sum xs

product []     = 1
product (x:xs) = x * product xs

sum関数とproduct関数のfoldを使った定義はこんな感じです。

sum     = foldr (+) 0
product = foldr (*) 1

確かに、に相当する部分と、値vに相当する部分がそれぞれ引数になっています。しかも、いつの間にか再帰がなくなりましたね。再帰的な様式を抽出するというのは本当みたいです。

Haskellはすべての関数がカリー化されるので、sumもproductもリストに適用すれば、結果が返ってきます。

わかりやすかった説明

で、前提は以上で、次に以下のような説明が続きます。

すなわち関数foldr f vは、空リストを値vに変換する。空でないリストに対しては、「先頭の要素」と「残りのリストに対し自分自身を呼び出した結果」に関数fを適用する。ただ実際には、foldr f vは再帰的に理解するのではなく、単にcons演算子を関数fに置き換え、末尾の空リストを値vに置き換えると理解する方がいいだろう。

という説明の後に具体例がこのようにきます。

1:(2:(3:[]))

これは、以下のように変換される。

1+(2+(3+0))

こういう説明、今まで見たことなくて、すごくわかりやすい説明だと思いました。
すべての関数を中置記法で使えるHaskellだからこそわかりやすいのかもしれませんが、他の言語でその機能の採用率が低めってだけと考えれば良いだけですし。

まとめるとfoldrのフォーマットは以下のような感じですね。

foldr f v [...]

で、次からは例です。

例: リストの値を合計する
foldr (+) 0 [1,2,3]

関数f = (+)
値v = 0

before:

1:(2:(3:[]))

cons演算子を関数fに置き換え、末尾の空リストを値vに置き換えてみる。

after:

1+(2+(3+0))
例: リストで最も大きい数値を求める
foldr max 0 [1,2,3]

関数f = max
値v = 0

before:

1:(2:(3:[]))

cons演算子を関数fに置き換え、末尾の空リストを値vに置き換えてみる。

after:

1`max`(2`max`(3`max`0))
例: リストの最初の要素を求める
getLeft :: a -> b -> a
getLeft a _ = a
foldr getLeft 0 [1,2,3]

関数f = getLeft
値v = 0

この例の場合、値vは即捨てるので、なんでもいいですが。

before:

1:(2:(3:[]))

cons演算子を関数fに置き換え、末尾の空リストを値vに置き換えてみる。

after:

1`getLeft`(2`getLeft`(3`getLeft`0))
例: リストの要素数を求める
succRight :: Enum a => a -> a -> a
succRight _ n = succ n
foldr succRight 0 [1,2,3]

関数f = succRight
値v = 0

before:

1:(2:(3:[]))

cons演算子を関数fに置き換え、末尾の空リストを値vに置き換えてみる。

after:

1`succRight`(2`succRight`(3`succRight`0))
例: リストを逆順にする
snoc :: a -> [a] -> [a]
snoc x xs = xs ++ [x]
foldr snoc [] [1,2,3]

関数f = snoc
値v = []

before:

1:(2:(3:[]))

cons演算子を関数fに置き換え、末尾の空リストを値vに置き換えてみる。

after:

1`snoc`(2`snoc`(3`snoc`[]))
例: リストの偶数の要素の合計値を求める
addEven :: Int -> Int -> Int
addEven n m  = if even n then m + n else m
foldr addEven 0 [1,2,3,4]

関数f = addEven
値v = 0

before:

1:(2:(3:(4:[])))

cons演算子を関数fに置き換え、末尾の空リストを値vに置き換えてみる。

after:

1`addEven`(2`addEven`(3`addEven`(4`addEven`0)))

foldr, foldlの要約

foldrの要約として以下の定義が掲載されていました。

foldr () v [x0, x1, ..., xn] = x0 (x1 (...(xn v)...))

で、foldrはが左結合であることが前提の関数で、foldlはが右結合であることが前提の関数だと。
foldlの定義も以下のように書かれています。

foldl () v [x0, x1, ..., xn] = (...((v x0) x1)...) xn

foldrかfoldlかでは、個人的には圧倒的にfoldlの方がわかりやすいので、foldl相当(reduceかreduceRightだったらreduce)ばかり使っていましたが、どちらでも実装できる場合は、より効率の良い方を選びましょうという話でした。
例えば、すごいH本には、(++)は(:)に比べると遅いので、リストを使って、リストを構築するようなケースでは、foldrを使う方が良いと書いてありました。後、無限リスト扱う時とか。consは右結合ですもんね。

まとめ

今までに比べてfold(r|l)関数の処理が頭の中で可視化されるようになった気がします。
あと、foldrに渡す関数は、定義がどれだけ複雑だったとしても、とどのつまり左被演算子が要素で右被演算子が累積値になる二項演算子的な関数で、foldlに渡す関数も、定義がどれだけ複雑だったとしても、とどのつまり、左被演算子が累積値で右被演算子が要素になる二項演算子的な関数なんだねって理解もできました。
今後は、リストを使った再帰を書くような時は、foldr, foldlに書き換えることもまず検討しようと思います。

*1:すごいH本の説明もわかりやすかったですよ

*2:PerlのList::Utilにあるreduceは好きになれませんが...

CSS Niteベスト・セッション2012でベスト・LTをいただきました && 本年もよろしくお願いします

CSS Niteベスト・セッション2012でベスト・LTをいただきました。

CSS Niteベスト・セッション2012

インストラクタをしていた時期が長かったので、人前で話すことは得意な方ですが*1、インストラクションとプレゼンテーションは共通部分も多いとは言え、異なるものなので、プレゼンテーションも上手にできたという事実は、個人的にはとても嬉しい事実でした。

何かを話す時、いつも良いパフォーマンスが出るわけではなく、ベスト・LTをいただいたトークでは、会場に知り合いが多く、かつ、2回目だったということもあり、緊張しすぎず、緩すぎず、反省も活きて、良いパフォーマンスが出たのかもしれません。

今後も「あいつは、口だけは達者やなー」と言われないように、実際のスキルや技術力を向上させていきたいと思います。

昨年は最後になって、いろいろ良いニュースが舞い込む年でした。本年もあと味をよろしくお願いいたします。

*1:福井弁ですけど...

Movable TypeのextlibディレクトリのCPANモジュールカタログ

Movable Type Advent Calender 2012の5日目です。

Movable Typeのプラグイン開発は、ダイナミック・パブリッシング対応のためにPHPを書くのを除いて、主にPerlのプログラムを書くことになります。

Perlのプログラムは、標準のモジュールだけで開発できることは少なく、様々なCPANモジュールを組み合わせて書いていくことが多いです。

プラグインの開発をする際、プラグインにCPANモジュールを同梱することもできますが、すでに同機能を実現できるモジュールが標準で用意されているのであれば、そちらをまずは使った方が、依存モジュール等でややこしくなくて済むので、まず、MT_HOME/extlibディレクトリの中にあるモジュールをいろいろと調べることがあります。

この機会に自分の備忘録も兼ねて、デフォルトのextlibディレクトリにある、CPANモジュールのカタログを作ってみました。

調査したバージョン

Movable Type 5.2(MTOS)

モジュールカタログ(アルファベット順)

以下、モジュールをアルファベット順に並べています。MT本体で利用されていない単なる依存モジュールかつ、個人的に使わなさそうなものは独断と偏見で省く可能性があります。ご了承下さい。

A

Algorithm::Diff
2つのファイル、リストの差違を求める関数を含んだモジュール。

MT本体では利用されていませんが、HTML::Diffの依存モジュールです。他に使えることもありそう。

Apache::*
mod_perl絡み。

MT5以降では、mod_perlをサポートしていないようなので、今後使わないのかもしれない。プラグイン開発には必要ないのかな。

Archive::Extract
圧縮ファイルの展開をする時に使うモジュール。

MT本体では使われていないようですが、Archive::ZipやArchive::ExtractのPODを見ると、解凍だけなら、こちらを使った方がメモリ消費量を節約できるっぽいです。(unzip等のコマンドが利用できる前提)

Attribute::Params::Validate
Params::Validateを属性を使って利用するモジュール。

特に使われているところは無さそうだけど。

AutoLoader.pm
AUTOLOADで呼ばれるメソッドをファイルに書きだしておけるモジュール。

Image::Sizeで使われてる。

C

CGI::*
言わずと知れたモジュールですね。

MT::Appで使われています。直接使うことは無さそう。

Cache::*
キャッシュのインターフェイス。

Data::ObjectDriverのサンプル・コードに出てくる程度。標準のextlibには入っていない、推奨モジュールのCache::Fileとか、Cache::Memcachedの方が有用そう。

Class::Accessor::*
アクセサの定義を簡単にするためのモジュール。

MT内でも使われているし、クラス作る時に有用。

Class::Data::Inheritable
アクセサの定義を簡単にするためのモジュール。Class::Accessorとの違いは、インスタンス変数へのアクセサか、クラス変数へのアクセサかです。

Data::ObjectDriver::Driver::BaseCacheでは、両方をClass::Accessor::FastとClass::Data::Inheritableとを使い分けています。

Class::Inspector
クラスについていろいろ検査するモジュール。

SOAP::Liteの依存モジュールのようです。とあるクラスをロード済みかどうか調べるのに使ってました。

Class::ErrorHandler
クラスのエラーメソッドを簡単に定義するためのモジュール。

URL::Fetchの依存モジュールのようです。

Class::Trigger
クラスにトリガーを設定するためのモジュール。

MTのフック・コールバックはこの仕組で実装してるっぽい。

Crypt::DH
DH法のためのモジュール。

Net::OpenID::Association等の依存モジュール。鍵作るのに必要みたい。

D

Data::ObjectDriver::*

ORマッパー。

MTで独自オブジェクト作る時は間接的にお世話になる。

F

File::Copy::Recursive

再帰的にファイルのコピーや移動をするためのモジュール。

MTでは、MT::CMS::Themeでエクスポートする時に使われている。

File::Listing

ファイルやディレクトリの一覧を出したい時などに使うモジュール。

LWP::Protocol::FTPで、ファイルの一覧をHTMLで返す時にファイル一覧ページを作るために使われている。

File::Tmp

TempファイルやTempディレクトリを作りたい時に使うモジュール。

MTでは、ファイルのアップロードで重複したファイル名の場合、上書きする時などに使われる。

H

HTML::Diff

二つのHTMLのdiffを取るモジュール。

MTでは、MT::Revisableで使われてますね。リビジョンの機能を使う時にお世話になってるってことです。

HTML::Form
HTMLのform要素をオブジェクトとしてパースするモジュール。

どこでも使われていなっぽいけど、LWP::UserAgentなんかと組み合わせて使うみたい。

HTML::Template
HTMLのテンプレートエンジン。

かつてのバージョンでは、MTの管理画面はHTML::Templateで書かれていたようで、その名残りだと思われます。MT::Builderには、HTML::Template形式のテンプレートをMTタグに変換するコードが入ってました。

H

HTTP::*
HTTPプロトコル周りのインターフェイス。

依存モジュールが大半で、MTでは、HTTP::RequestとHTTP::Response、HTTP::Dateあたりが実際に使われています。

Heap::Fibonacci
フィボナッチヒープを取り扱うモジュール。

MT内では使われていなくて、Cache::Memoryの依存モジュール。

フィボナッチヒープ自体、何が良いのか一度作ってみないと理解不能な感じなので、よくわかりません。

I

I18N::LangTags::*
RFC3066形式の言語タグを取り扱う関数をエクスポートするモジュール。

Locale::Maketextの依存モジュールで、MT::L10Nでも使われてます。言語タグから言語名を取得するのに使ってるだけかな。

IO::Scalar
スカラ変数をファイルハンドルっぽく扱うためのモジュール。

MTでも依存モジュールでも使ってなさそう。

IO::WrapTie
IO::Handleインターフェイスでtieされたオブジェクトを扱うためのモジュール。

IO:Scalarの依存モジュール。

IPC::Cmd
外部コマンドをPerlから簡単に実行するためのモジュール。

MTでは直接利用していない。Archive::Extractの依存モジュール。tarコマンドやらzipコマンドやらを使う時に利用されている。

Image::Size
画像のサイズを取得するためのモジュール。

MT内でも、MT::Imageや、MT::Asset::Image等、画像サイズの取得が必要な場面で利用されている。

J

JSON::*
PerlでJSONを取り扱うためのモジュール。

MT内でもJSONを取り扱う箇所でいろいろ使われています。

L

LWP::*
PerlのWWWクライアントツール群。

MTでは、主に、LWP::UserAgentが外部サイトへのアクセス等で背面化でいろいろ働いてます。MT->new_uaで、MT用にカスタマイズされたUserAgentが作れるようになっています。

Locale::Maketext
ローカライゼーションのためのフレームワーク

MTのローカライゼーションの基盤です。プラグイン開発で使う、translate関数の元です。

Lucene::QueryParser
全文検索ソフトLuceneののクエリパーサ。

MTでは、MT::App::Search等で使っていて、検索クエリの解析に使ってるみたい。

M

MIME::Charset
MIMEのためのCharset情報を扱うモジュール。

MTでは直接使っていなくて、MIME::EncWordsの依存モジュール。

MIME::EncWords
RFC2047形式でエンコードされた文字を扱うためのモジュール。

MT::Mailでメールのヘッダをエンコードするのに使われている。

Math::BigInt
BigIntを扱うためのモジュール。

MT::Utilのdsa_verifyで、Crypt::DSAがない時に、これを使ってなんとかしている。

Module::Load
モジュールローダー。

Module::Load::Conditonalの依存モジュール。

Module::Load::Conditional
モジュールの情報によってロードするモジュールローダー。

MT内では使われていませんが、Archive::ExtractやIPC::Cmdの依存モジュールで、can_loadメソッドが使われています。

N

Net::HTTP
HTTPクライアント。

MT内では使われていません。LWP::Protocol::httpやNet::HTTPSの依存モジュール。

Net::HTTPS
HTTPSクライアント。

Net::HTTPと同じく、LWP::Protocol::httpsの依存モジュール。

Net::OAuth
PerlでOAuthを扱うためのモジュール。

もしかしたらコマーシャルパックでは利用するのかもしれませんが、MTOSでは利用してなさそう。

Net::OpenID::*
PerlOpenIDを扱うためのモジュール。

MTでは、MT::Auth::OpenIDで使われています。コメント投稿時にOpenID使う時とか。

P

Parms::Check
関数の引数をチェックするモジュール。

MT内では使われていません。Archive::Extractや、Module::Load::Conditional等で引数チェックに使われています。

Params::Validate
関数の引数をバリデートするためのモジュール。

MT内でも、何かの依存モジュールでもなさそう。

S

SOAP::*
SOAP関連のモジュール群。

MTでは、MT::XMLRPCServer等で使われている。

T

TheSchwartz::*
ジョブキューシステムTheSchwartz関連モジュール。

SixApart製ということもあり、MTのジョブキューシステムはこれで管理されている。

U

UDDI::Lite
UDDIクライアント。

MT内で使われてなさそう。

UNIVERSAL::require
モジュールローダーのひとつ。

Net::OAuthで使われている。

URI::*
URIPerlのインターフェイス。

MT内では、MT::App::Wizard、MT::AtomServer等、URIを分解する時等に利用されている。

W

WWW::RobotRules

MT内では直接使われてません。LWP::RobotUAの依存モジュール。

X

XML::Atom
ATOMのインターフェイス。

MTでも、MT::AtomやMT::AtomServer等、ATOM関連で使われている。

XMl::Elemental
XMLPerlオブジェクトにパースするモジュール。

XMl::Parser::Style::Elementalの依存モジュール。1

XML::Parser::Lite
正規表現ベースのXMLパーサ。

特に使われていない。

XML::NamespaceSupport
XMLのnamespaceのインターフェイス。

XML::SAXやXML::Simpleの依存モジュール。

XML::SAX
SAXパーサ。

MT::Utilで使われていて、MT::BackupRestoreに必要なモジュールになるので、ブログのバックアップと復元機能が使えなくなる。

XML::Simple
簡単に使えるXMLインターフェイス。

MT内では直接使われてないけど、XML扱う時には使えそう。

XML::XPath
XPathに基づくXMLパーサ。

MT内では、MT::AtomServerとMT::Auth::OpenIDで使われている。

XMLRPC::Lite
XMLRPCのPerl実装。

MT内では直接使われていませんが、XMLRPC::Transport::*の依存モジュール。

XMLRPC::Transport::*
XMLRPC::Liteの様々なプロトコルの実装。

mt-xmlrpc.cgiで、XMLRPC::Transport::HTTPが使われている。

Y

YAML::Tiny

YAMLファイルを読んだり書いたりするモジュール。

MTでは、MT::Util::YAML::Tinyという名で再定義されている。

V

version::*

バージョンオブジェクトを扱うためのモジュール。

まとめ

思ったより、必要最小限のモジュールしか使ってないなという印象がありました。やはりいろんな環境で動かそうと思うと、依存多すぎてもいけないってのがあるのかもしれませんね。extlib配下のモジュールのものでも、Perlのバージョンによっては標準モジュールになっているものもたくさんあります。

toolsの中に突如Web::Scraper依存のコードがあったり、コード書く人によって、違うのかもしれませんが。

どこで使われているかよくわからないものもありましたが、今回調べたバージョンで使われていなかったり、MTOSでは使われていないものもあったのかもしれません。

Tips

特定のモジュールが特定のPerlのバージョンの標準モジュールかどうかを調べるには、Module::CoreListが便利です。corelistというコマンドがインストールされるので、それを使えば標準モジュールを調べられます。

$ cpanm install Module::Corelist
$ corelist --help
$ corelist -a Module::Load

また、依存モジュールも含めてローカル領域にCPANモジュールをインストールするには、cpanmコマンドの方が楽でしょう。XS依存の部分はサーバーに単純に上げても使えませんが、*::PPとか書いてあるモジュール探すとか、metacpanでpure perlと検索して探して解決するとかで対処する感じですね。

$ cpanm -h
$ cpanm -L ./extlib Plack

cpanmのインストール等、Perlの環境構築については、あと味の[Perlの環境構築 - あと味などを参考にしていただければと思います。

最後に

来年はMovable Typeに本気で取り組みます。

Perlのリストのおもしろいところ

PerlのリストはPerlらしいというか、結構おもしろいなーと思うことがあります。

Perlのリストの面白いところを紹介してみます。

cons, append

Perlでconsとかappendするいい方法何かなーとか考えてた時に、リストの標準機能でできることに気づきました。

my @one_to_three  = (1, 2, 3);

# cons
my @zero_to_three = (0, @one_to_three);

# append
my @one_to_four = (@one_to_three, 4);

concat

同じような方法でconcat相当もできます。

my @one_to_three  = (1, 2, 3);
my @four_five_six = (4, 5, 6);

# concat
my @one_to_six = (@one_to_three, @four_five_six);

ハッシュ版cons, append, concat

Perlでハッシュを定義する時は、以下のように定義します。

my %foo_bar = (foo => 1, bar => 2);

これはいろんな書籍に書いてあることですが、以下の別記法です。

my %foo_bar = ('foo', 1, 'bar', 2);

ハッシュはkeyとvalueが対になったハッシュをリストコンテキストで評価すれば、ハッシュになるわけですね。

この特徴を利用すれば、ハッシュ版のcons, append, concatも可能になります。

my %foo_bar = (foo => 1, bar => 2);
my %baz_qux = (baz => 3, qux => 4);

# ハッシュ版cons
my %hoge_foo_bar = ('hoge' => 0, %foo_bar);

# ハッシュ版append
my %foo_bar_hoge = (%foo_bar, hoge => 3);

# ハッシュ版concat
my %foo_bar_baz_qux = (%foo_bar, %baz_qux);

面白いですね。

car(head), cdr(tail)

関数型言語でよくあるcar(head), cdr(tail)などもリストの標準の機能でOKです。これくらいのことをするのに、イチイチ関数なんていらんかったんです。

my ($car, @cdr) = (1, 2, 3, 4);

多値っぽいもの

多値っぽいものもできます。

my $zero = 0;
my $one  = 1;
my $two  = 2;

# リストの各要素に10足したリストを返す関数
sub map_add_10 {
  map { $_ + 10 } @_;
}

my ($ten, $eleven, $twelve) = map_add_10($zero, $one, $two);

便利ですね。

分配束縛っぽいもの

引数を分解するのも簡単です。超単純なheadとtailを関数にしてみましょう。(先ほどいらんかったんですって言ったとこですが...)

sub head {
  my ($x, @xs) = @_;
  $x;
}

sub tail {
  my ($x, @xs) = @_;
  @xs;
}

my $head = head(1, 2, 3);
my @tail = tail(1, 2, 3);

補足

面白いんですけど、リストは1次元しか表現できないので、2次元以上はこのワザは使えません。

ちなみに最近まで、同一視していたんですけど、配列とリストはPerlでは別物という扱いだそうです。

参考: リストと配列(Array)はPerlでは別物 - Togetter

まとめ

Perlのリストおもしろいですね。*1

*1:ただ、Perl関数プログラミングするのは、個人的には微妙な感じしてます