我想在Mojolicious中创建一个递归模板块,从嵌套数组生成复杂的菜单.
理想情况下,数组["a", ["ba", "bb"], "c"]
将导致此嵌套列表:
<ul>
<li>a</li>
<li>
<ul>
<li>ba</li>
<li>bb</li>
</ul>
</li>
<li>c</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
以下代码不起作用,因为块是匿名子例程,不能使用对自己的引用:
% my $block = begin
% my $menu = shift;
<ul>
% foreach my $item (@{$menu}){
% if(ref($item) eq 'ARRAY') {
<li>
%= $block->($item);
</li>
% } else {
<li><%= $item %></li>
% }
% }
</ul>
% end
%= $block->( ["a", ["ba", "bb"], "c"] )
Run Code Online (Sandbox Code Playgroud)
要在表达式中使用变量,您需要在表达式之前声明此变量.所以,这将工作:
% my $block; $block = begin
但是会产生内存泄漏,因为$ block现在是一个循环引用,当它超出范围时perl无法删除.从perl 5.16开始,你可以在anonymous sub中使用__SUB__关键字来获取对这个子例程的引用.所以这就简单了
% use v5.16;
% my $block = begin
...
__SUB__->($item)
...
% end
Run Code Online (Sandbox Code Playgroud)
如果你想在perl <5.16上运行你的代码,你可以使用替代方法来避免内存泄漏.只是不要使用闭包,而是将对块的引用作为参数传递
% my $block = begin
% my ($block, $menu) = @_;
...
%= $block->($block, $item);
...
% end
%= $block->( $block, ["a", ["ba", "bb"], "c"] )
Run Code Online (Sandbox Code Playgroud)