プログラミング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は右結合ですもんね。
CSS Niteベスト・セッション2012でベスト・LTをいただきました && 本年もよろしくお願いします
CSS Niteベスト・セッション2012でベスト・LTをいただきました。
インストラクタをしていた時期が長かったので、人前で話すことは得意な方ですが*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の依存モジュールです。他に使えることもありそう。
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等、画像サイズの取得が必要な場面で利用されている。
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::HTTPと同じく、LWP::Protocol::httpsの依存モジュール。
Net::OAuth
PerlでOAuthを扱うためのモジュール。
もしかしたらコマーシャルパックでは利用するのかもしれませんが、MTOSでは利用してなさそう。
P
Parms::Check
関数の引数をチェックするモジュール。
MT内では使われていません。Archive::Extractや、Module::Load::Conditional等で引数チェックに使われています。
Params::Validate
関数の引数をバリデートするためのモジュール。
MT内でも、何かの依存モジュールでもなさそう。
T
TheSchwartz::*
ジョブキューシステムTheSchwartz関連モジュール。
SixApart製ということもあり、MTのジョブキューシステムはこれで管理されている。
U
UDDI::Lite
UDDIクライアント。
MT内で使われてなさそう。
UNIVERSAL::require
モジュールローダーのひとつ。
Net::OAuthで使われている。
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
XMLをPerlオブジェクトにパースするモジュール。
XMl::Parser::Style::Elementalの依存モジュール。1
XML::Parser::Lite
正規表現ベースのXMLパーサ。
特に使われていない。
XML::NamespaceSupport
XMLのnamespaceのインターフェイス。
XML::SAX
SAXパーサ。
MT::Utilで使われていて、MT::BackupRestoreに必要なモジュールになるので、ブログのバックアップと復元機能が使えなくなる。
XML::Simple
簡単に使えるXMLインターフェイス。
MT内では直接使われてないけど、XML扱う時には使えそう。
MT内では、MT::AtomServerとMT::Auth::OpenIDで使われている。
XMLRPC::Lite
XMLRPCのPerl実装。
MT内では直接使われていませんが、XMLRPC::Transport::*の依存モジュール。
XMLRPC::Transport::*
XMLRPC::Liteの様々なプロトコルの実装。
mt-xmlrpc.cgiで、XMLRPC::Transport::HTTPが使われている。
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);
簡易的なuniqメソッド(文字列限定)を書いたので、underscore.jsのuniqメソッドとベンチマーク取ってみました
グリモンを書いてて、uniqメソッドを自前で作ろうと思ったのですが、少し面白い方法を見つけたので、jsPerfでベンチマークしてみました。文字列専用ですが。
自前のuniqメソッド
オブジェクトを構築する際に、キーはひとつのオブジェクトに対してユニークになるので、適当な値を突っ込んでオブジェクトを構築し、最後にキーだけ取り出す感じです。reduceを使えば、4行程度で書けます。
まとめ
文字列限定ですが、underscore.jsのuniqメソッドで、最適化オプションなしの状態より速い場合が多いようです。
ただ、Google Chromeでは、underscore.jsの最適化オプションがfalseでも、今回作ったuniqメソッドよりも速いので、実用的かどうかは微妙なところです。
Object.keysメソッドが遅いのかな?それとも、バイナリサーチが得意なのかな?よくわかりません。
追記
@hokaccha さんとのやり取り。
@taiju reduceのコストが高いのかなーと思ってforでやってみました。ブラウザによってはunderscoreより速いですね。 bit.ly/VWH6Ka
— Kazuhito Hokamura (@hokaccha) November 12, 2012
@hokaccha ありがとうございます!やっぱ、速度求めるとどうしてもforに軍配があがるんですねー。isSorted=trueのバイナリサーチより速いスコアが出てるブラウザがあるとは、分岐等の処理のコストは結構あるんですね。
— taiju (id:jdg) (@taiju) November 12, 2012
@taiju 分岐のコストというよりeachでループ毎に無名関数でスコープつくるにコストかかってるんじゃないかと思います。reduceよりforのが速いのも同じ理由な気がします。
— Kazuhito Hokamura (@hokaccha) November 12, 2012
@hokaccha 追加してみたんですけど、無名関数のコストはそんなにないっぽいです。reduce遅いのかな。 jsperf.com/string-uniq-fo…
— taiju (id:jdg) (@taiju) November 12, 2012
@taiju なるほどー。関数呼び出しのコストかなーと思ったんですけどブラウザによって違いすぎてよくわからなくなってきましたw bit.ly/ZeOH6E
— Kazuhito Hokamura (@hokaccha) November 12, 2012
@hokaccha Chromeが一番謎なスコアな気がしますけど、ほんとよくわかんないですねw
— taiju (id:jdg) (@taiju) November 12, 2012
@taiju たぶんV8の謎な高速化が働いてるんでしょうねw
— Kazuhito Hokamura (@hokaccha) November 12, 2012
悔しいですけど、for速いですね。
MovableTypeのモジュールのPODのViewerプラグイン作った
MovableTypeを触っていると、MTのモジュールのPODを見る機会が多くなります。MTタグの使い方とかも該当モジュールのPOD見れば解決することもあるので、とりあえずアイデアレベルですが、昨日作ってみたのでエントリー起こしました。
MTPodViewerという名前を付けました。
デモサイト
インストール
リポジトリにあるplugins/MTPodViewer
をサイトのplugins
にコピーします。加えて、リポジトリにあるmt-static/plugins/MTPodViewermt-static/plugins
にコピーします。
依存モジュールはextlib
に同梱したつもりですが、動かなかったらごめんなさい。cpanコマンドかcpanmコマンドでインストールしてください。依存モジュールは、plugins/MTPodViewer/Makefile.PL
に書いてあります。
プラグイン設定
システムのプラグインに進むと1箇所だけ設定があります。
ログイン必須にするかしないかの選択です。Yesならログイン必須、Noならログイン不要です。
検索方法
たとえば、MTのディレクトリで、perldocする場合、以下のような感じになると思います。
$ perldoc lib/MT/App.pm
MTPodViewerでは、以下の様なキーワードで検索することになります。
app
MT::Template::Tags::Entryを検索したい場合は、
template-tags-entry
と検索します。
MTというプレフィクスは省略して、「/」や「::」の区切り文字を「-」にして、全部小文字にしているということです。
bootstrapのtypeaheadがある程度面倒見てくれるので、これで充分な気がしてます。
感想
最初はCSSとか自分で書いてたんですけど、途中からbootstrapに変更しました。bootstrap-typeaheadのスタイル作るの面倒だったので...。というか基本的にbootstrapは何かと楽でマジ助かります。
見出しのフォントはHelvetica、本文のフォントはGoogle Web Fontsにある、OpenSansにしました。すごく読みやすいですね、このフォント。
速度的にはちょっと微妙なので、モジュール一覧をキャッシュしておくなりした方がいいと思いますが、また気が向いたら対応します。
リンクの部分とかは、Pod::Simple::XHTMLの吐き出すソースをちょっとカスタマイズしたらうまくできるのかもしれませんが、ページ内リンクと別モジュールへのリンクがうまく場合分けできなさそうなので、リンクをすべて外すって対応を取っています。
MTアプリケーションはMTをWAFと思えば、普通に使えますね。クライアントワークだったら、依存モジュールの解決もそんなに面倒じゃないですし、最近は、MTアプリケーション作る機会もあって、いろんなCPANモジュールと組み合わせて使ってます。
あと、英語のドキュメント書けない。深刻。
kanazawa.rbで「Mojoliciousと愉快なPerl」という話をしてきました
つい先程の話。kanazawa.rbで「Mojoliciousと愉快なPerl」という話をしてきました。
Perlの記事を書いたことはあるけど、Perlについての発表をするのは初めてだったので、いつも以上に緊張した感じです。というか、ようやくプログラムの話ができるようになったという感じでしょうか。
話の内容
スライドにはキーワードだけ書いて、口頭での説明とデモがメインだったので、スライドだけ読んでもちょっと物足りないかもしれません。
発表でも話しましたが、かつてはRubyがPerlから学ぶことが多かったけれど、今はPerlがRubyから学ぶことが多いです。
Rubyの勉強会に参加するのも初めてでしたが、多分、Perlの人がRubyの勉強会に参加するのは、少し先の未来を覗き見することにもなるのかなと思います。
今回はSinatra vs Mojolicious vs Expressみたいな構図でしたが、それぞれパクリ愛に溢れていて、どれも素晴らしいものだと思いました。
ですが、発表の準備をするにあたり、Mojoliciousをいろいろ調べ直してみると、やっぱりMojoliciousが好きです。ひいきなしで、自分はSinatraよりも、Expressよりも、Mojoliciousが好きだなぁと。
Mojoliciousは、標準モジュール以外、すべて自前で用意しているし、どのCPANモジュールを使えばいいかわからないという人でも、とりあえず、Mojoliciousの用意しているモジュールやツールを使えば、Perlで簡単なWebアプリケーションを書くことができるでしょう。
今回の発表では、デモも交えて説明したのですが、Perl使うならperldocをたくさん使いましょうねっていう話をしました。
Rubyのドキュメントの文化とかはよく知りませんが、Perlはドキュメントがちゃんと整っているし、ちゃんと書かないといけない印象で、しかもperldocってツールが最高に使いやすいです。
PODという発明、良いプログラマは良い物書きでもあるという教えが、この文化を生んだのかなと思います。
まとめと反省
Rubyの勉強会に参加することで、Rubyの人になる可能性もありますが、もはや、Perlのキモかわいさに慣れてしまって、なかなか難しいような気もしています。*1
去年のYAPC::Asia TOKYO2011に参加して、感想記事を書いた中で、来年のYAPC::Asiaまでに、CPAN Authorになりたいとか、次回のYAPCではLTに出たいとか書いていましたが、結局この目標は未達になってしまいました。。。*2
自分を慰めるとすれば、Perlの勉強会ではないにせよ、Perlの発表をすることができたのと、Perlでツールを作って公開するということはできたという点でギリギリ赤点でしょうか。もっと精進します。