Xslateの関数でクロージャを使う

[twitter:@shmorimo]さんとのやりとりのなかで考えた、Xslateの関数にクロージャを渡したいケースのまとめです。
まず前提条件:

  • リクエスト毎にクロージャをXslateに渡したい
  • Xslateの登録関数を定義できるのはnew()のときのみ
    • 動的に関数を加えることはできない
  • リクエスト毎にXslateをnewすると遅いので避けたい

このような条件下で、リクエスト毎にクロージャを登録する方法は幾つかあります。

render()のパラメータとして渡す

KolonにせよTTerseにせよ、値に()演算子を適用すると関数を呼び出せます。したがって、単にrender()のパラメータにクロージャを渡すことで関数呼び出しができます。

#!perl -w
use strict;
use Text::Xslate;
my $tx = Text::Xslate->new();
print $tx->render_string(<<'KOLON', { f => sub { 'Xslate' }});
Hello, <: $f() :> world!
KOLON
__END__

プレースホルダを登録して中身を書き換える

関数としての体裁を保ちたい場合、中身だけ書き換えるという手もあります。しかし、スクリプトの可読性は低くなります。

#!perl -w
use strict;
use Text::Xslate;
my $f_body;
my $tx = Text::Xslate->new(
    function => { f => sub { goto $f_body } },
);
$f_body = sub { 'Xslate' };
print $tx->render_string(<<'KOLON', { });
Hello, <: f() :> world!
KOLON
__END__

いまのところ、この二つが素直なやり方だと思います。他にも考えているのですが、今のところいい方法が思い浮かばないのでとりあえずこんなところで。