Text::Xslate TTerse の深淵なる罠

tag perl template xslate

みなさんこんにちわ!みなさんはテンプレート使ってますね! Xslate つかってますね! TTerse 使ってますね!今回はうっかりハマってしまう罠を教えます!

SET で作った変数はブロックスコープである

ブロックスコープなんだけど SET したスコープの中にあるブロックはスコープの対象外なので以下のテストは動かなかったりするんだ。

my $tx = Text::Xslate->new({
    syntax => 'TTerse'
});
my $ret = $tx->render_string(<<TMPL,);
[% SET chin = 'kiru' -%]
[% MACRO xaicron BLOCK -%]
[%   chin = 'kiranai' -%]
[%   chin -%]
[% END -%]
[% xaicron() -%]
[% chin -%]
TMPL
is $ret, "kiranaikiranai"; # kiranaikiru が帰って来て失敗する                                                                                                                                       

実は SET は飾り

変数の定義しなくても最初に出て来た時に SET したのと同等っぽいね。だから上のコードの xaicron マクロの中の最初の chin ってのは SET したのと同等ってわけさ。

深遠な理由で例外がある

色々あって次のようなケースはブロックスコープになってないんだけど、これ直しちゃうと影響範囲でかすぎるからきっとこのままっぽいね。

my $tx = Text::Xslate->new({
    syntax => 'TTerse'
});
my $ret = $tx->render_string(<<TMPL,);
[% SET chin = 'kiru' -%]
[% IF 1 -%]
[%   SET chin = 'kiranai' -%]
[%   chin -%]
[% END -%]
[% chin -%]
TMPL
is $ret, "kiranaikiru"; # kiranaikiranai が帰って来て失敗する                                                                                                                                       

あと関係無いけどこれの ELSIF の中での chin の定義で Text::Xslate::Compiler: Cannot modify chin, which is not a lexical variable って言われるんだけど(1.6001現在)これはバグなんで gfx が直してくれるはず!

[% IF 1 -%]
[%   SET chin = 'kiru' -%]
[% ELSIF 0 -%]
[%   SET chin = 'kiranai' -%]
[% END -%]                                                                                                                                                                                              

SET つかったら負け

基本的にはテンプレートでは複雑な事したら負けだし SET とかで頑張ってロジック組んじゃうとか愚か者なんだって!

要はSETをエイリアス以外の用途で使うなってことです! / “Text::Xslate TTerse の深淵なる罠 - Perl Advent Calendar Japan 2012 Casual Track” htn.to/F4WZ3j

— Fuji, Goroさん (@__gfx__) 12月 19, 2012

ってことで hacker track も casual track も誰か書いてくれないかなー!?