クロージャの使用例 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;
}
と書けたらいいかもとか少し思った。