从模板工具包中的代码参考调用

时间:2018-08-27 03:43:38

标签: perl method-call template-toolkit

我有一个简单的高阶函数来构建消息格式化程序。

use strict;
use warnings;

sub make_formatter {
    my $level = shift;
    return sub {
        my $message = shift;
        return "[$level] $message";
    }
}

我从Perl这样使用它:

my $component_formatter = make_formatter('ComponentError');
print $component_formatter->('Hello') . "\n";

我想使用模板工具包模板中的make_formatter。我尝试执行以下操作:

use Template;
use Template::Constants;

my $template = Template->new({
#   DEBUG => Template::Constants::DEBUG_ALL,
    VARIABLES => {
        make_formatter => make_formatter,
    }
});

my $template_str = "
[% my_formatter = make_formatter('MyFormatter') %]
<h1>[% my_formatter('Sample message') %]</h1>
";

$template->process(\$template_str);

此脚本的输出为:

$ perl test.pl 
Use of uninitialized value $level in concatenation (.) or string at test.pl line 10.


<h1>[] MyFormatter</h1>

是否可以仅使用模板工具包语法来调用my_formatter?不能选择默认情况下无法从模板工具包中调用外部Perl代码。

1 个答案:

答案 0 :(得分:2)

首先请允许我指出,强烈建议在脚本的开头放置use strict; use warnings;

如果您针对生成$ template的代码段执行此操作, 您将收到一个Bareword "make_formatter" not allowed while "strict subs" in use错误,这应该有助于您确定这不是一个有用的符号。

现在,如果您改为呼叫make_formatter(),则将输出<h1>[] MyFormatter</h1>。这是有道理的:您的函数返回了子模板,该子模板在模板中被称为“ MyFormatter”($ level为undef,就像您在没有输入的情况下调用make_formatter一样)。

正如海格兰德先生指出的那样,

my $template = Template->new({
VARIABLES => {
    make_formatter => \&make_formatter,
}
});

导致我理解您想要的输出:

<h1>[MyFormatter] Sample message</h1>

\&make_formatter给您一个子例程引用, 在perl中通常可以使用以下命令进行调用: my $ref = \&make_formatter; $ref->( 'Input' );

然后可以在模板的第一行中调用它, 返回另一个代码引用,然后在第二行中调用。

希望这会有所帮助!