Template-Toolkit で [ 1 .. N ] を使ってみる

以下は Template-Toolkit じゃなければ絶対できなそうな技ですが、ページャを作るときに重宝しそうです。

<ul>
[% FOREACH i = [ 1 .. c.stash.max ] %]
<li>[% i %]</li>
[% END %]
</ul>

ちなみに、以下を定義しておくとテンプレートがどのように Perl のコードに変換されているのか詳細に見ることができます。

$Template::Parser::DEBUG = 1;
$Template::Directive::PRETemplate::ToolkitY = 1;

こんな感じに変換されます。

# FOREACH 
do {
    my ($value, $error, $oldloop);
    my $list = [ 1..$stash->get(['c', 0, 'stash', 0, 'max', 0]) ];
    
    unless (UNIVERSAL::isa($list, 'Template::Iterator')) {
        $list = Template::Config->iterator($list)
            || die $Template::Config::ERROR, "\n"; 
    }

    ($value, $error) = $list->get_first();
    eval { $oldloop = $stash->get('loop') };
    $stash->set('loop', $list);
    eval {
LOOP:   while (! $error) {
            $stash->{'i'} = $value;
            $output .=  "\n<li>";
            $output .=  $stash->get('i');
            $output .=  "\n";;
            ($value, $error) = $list->get_next();
        }
    };
    $stash->set('loop', $oldloop);
    die $@ if $@;
    $error = 0 if $error && $error eq Template::Constants::STATUS_DONE;
    die $error if $error;
};

Template-Toolkit にはキャッシュ機構があるので、テンプレートが変更されない限りこの変換は一度だけ行なわれます。