Perl:用于数组定义的括号与括号,为什么一个被认为是标量?

Gus*_*uma 1 arrays perl perl-html-template

我在Perl的HTML :: Template模块上学习教程.这是模板:

<!--template2.tmpl-->
<html>
<body>
<table>
  <tr>
    <th>Language</th>
    <th>Description</th>
  </tr>
  <tmpl_loop name="language">
  <tr>
    <td><tmpl_var name="language_name"></td>
    <td><tmpl_var name="description"></td>
  </tr>
  </tmpl_loop>
</table>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

这是CGI测试程序:

#!"C:\Strawberry\perl\bin\perl.exe" -wT
use CGI qw(:all);
use CGI::Carp qw(fatalsToBrowser);
use HTML::Template;

my @rows = (
  {
    language_name => 'C#',
    description   => 'Created by Microsoft'
  },
  {
    language_name => 'PHP',
    description   => 'Hypertext Preprocessor'
  },
  {
    language_name => 'Haskell',
    description   => 'Functional language'
  },
);

print header;
my $template=HTML::Template->new(filename=>'template2.tmpl');
$template->param(language => @rows);
print $template->output();
Run Code Online (Sandbox Code Playgroud)

此操作失败,并显示以下错误: HTML::Template::param() : attempt to set parameter 'language' with a scalar - parameter is not a TMPL_VAR!

但是,当我将@rows的定义从使用括号更改为使用方括号(从my @rows=(...)my @rows = [...])时,代码工作正常; 它显示一个包含数据的表.

正如我从阅读理解文章,第一种形式是从一个列表中定义的阵列,并且第二个是一个匿名数组的引用.我仍然不清楚为什么第一种形式不起作用.我很感激你为我澄清这一点.

Sue*_*mme 7

您所关注的教程包含错误.这条线

$template->param( language => @languages );
Run Code Online (Sandbox Code Playgroud)

应该

$template->param( language => \@languages );
Run Code Online (Sandbox Code Playgroud)

为什么?简短回答:传递给的循环名称的右侧param必须是对数组的引用,而不是数组.

答案很长:当您将参数传递给函数或方法时,所有参数都会扩展为一个长列表.这是初学者常见的错误来源.因此,在你的代码(在本教程的代码),你不能传递两个参数的param方法,你传递4(一个用于字符串"语言",而三为@languages的元素.

以下是此参数列表解析的示例.如果您有三个变量,如下所示:

my $scalar = 'bear';
my @array  = ('rat', 'moose', 'owl');
my %hash   = (mass => 500, units => 'kg');
Run Code Online (Sandbox Code Playgroud)

并将它们传递给这样的函数:

some_function($scalar, @array, %hash);
Run Code Online (Sandbox Code Playgroud)

那么函数会看到8个参数:'bear','rat','moose','owl','mass',500,'units',和'kg'!也许更令人惊讶的是,散列中的两组值可能以不同的顺序传递,因为散列不是以确定的顺序存储或检索的.

您将括号更改为方括号的解决方案有效,但不是很好的理由.括号分隔列表(可以存储在数组或散列中); 方括号分隔对数组的引用.因此,您的方括号代码会创建对匿名数组的引用,然后将其存储为命名数组的第一个(也是唯一的)元素@rows.相反,您应存储在一个标量变量数组引用(用方括号分隔)(比方说,$rows),或者应该使用括号,该列表存储在阵列中@rows,并传递给该数组的一个参考param方法(通过使用一个反斜杠,正如我上面所做的那样\@languages).