クロージャの使用例 in Text::Hatena
id:naoya氏がclosureのpracticeをいくつか揚げていて非常に勉強になります。
ちょっと思いだしたのは、Text::Hatenaに含まれるText::Hatena::HTMLFilterで、HTML::Parserを
$self->{parser} = HTML::Parser->new( api_version => 3, handlers => { start => [$self->starthandler, 'tagname, attr, text'], end => [$self->endhandler, 'tagname, text'], text => [$self->texthandler, 'text'], comment => [$self->commenthandler, 'text'], }, );
こんな感じで呼び出しています。
各handlerがどうなっているのかと言えば、
sub texthandler { my $self = shift; return sub { my $text = shift; $text = &{$self->{context}->texthandler}($text, $self->{context}); $self->{html} .= $text; } }
のようになっていて、「$self」を保持しつつ無名サブルーチンを返しています。
実はこの方法を最近まで知らなくて、クロージャも理解してなく、HTML::Parserを継承してパーサクラスを書いてますた。ようやくきちんと理解できた気がする。
ところで、この連休はJavaScript(prototype.js有り)をずっと書いていたおかげで、
sub parser{ $self->{parser} = HTML::Parser->new( api_version => 3, handlers => { start => [$self->starthandler->bind($self), 'tagname, attr, text'], end => [$self->endhandler->bind($self), 'tagname, text'], text => [$self->texthandler->bind($self), 'text'], comment => [$self->commenthandler->bind($self), 'text'], }, ); } sub texthandler { my $self = shift; my $text = shift; $text = &{$self->{context}->texthandler}($text, $self->{context}); $self->{html} .= $text; }
と書けたらいいかもとか少し思った。