因为 eugene 和 mugen 已经用很好的例子很好地回答了这个问题,所以我将设置一些概念,然后询问 OP 的一些概念性问题,看看它是否有助于阐明一些 Perl 概念。
第一个概念是符号$ 和@ 的含义(我们不会在这里讨论%)。 @ 表示多个项目(说“这些东西”)。 $ 表示一项(表示“这件事”)。要获取数组@a 的第一个元素,您可以执行$first = $a[0],获取最后一个元素:$last = $a[-1]。注:不是@a[0] 或@a[-1]。您可以通过 @shorter = @longer[1,2] 进行切片。
第二个概念是void、标量和列表上下文的区别。 Perl 具有使用容器(标量、数组等)的上下文的概念。看到这一点的一个简单方法是,如果您将列表(我们将得到这个)存储为数组@array = ("cow", "sheep", "llama"),那么我们将数组存储为标量$size = @array,我们得到数组的长度。我们还可以通过使用scalar 运算符(例如print scalar @array)来强制执行此行为。为了清楚起见,我再说一遍:标量上下文中的数组(不是列表)将返回,而不是元素(如列表那样),而是数组的长度。
请记住,当您只期望一项时,使用 $ 印记之前,即 $first = $a[0]。通过这种方式,您知道您处于标量环境中。现在,当您调用$length = @array 时,您可以清楚地看到您在标量上下文中调用数组,因此您在列表上下文中触发了数组的特殊属性,您会得到它的长度。
这还有一个很好的功能可以测试数组中是否有元素。 print '@array contains items' if @array; print '@array is empty' unless @array。 if/unless 测试在数组上强制标量上下文,因此 if 看到数组的长度而不是它的元素。由于除零之外的所有数值都是“真实的”,因此如果数组的长度非零,则 if @array 语句的计算结果为 true,您将得到 print 语句。
空上下文意味着某些操作的返回值被忽略。在 void 上下文中一个有用的操作可能类似于递增。 $n = 1; $n++; print $n; 在此示例中,$n++(返回后递增)处于 void 上下文中,因为未使用(存储、打印等)其返回值“1”。
第三个概念是列表和数组的区别。列表是一组有序的值,数组是一个包含一组有序值的容器。例如,您可以在体操中看到差异,在使用 sort 后必须先获取特定元素,而无需先存储结果(例如,尝试 pop sort { $a cmp $b } @array,这不起作用,因为 pop 不作用于列表,仅一个数组)。
现在我们可以问,当您尝试您的示例时,您希望 Perl 在这些情况下做什么?正如其他人所说,这取决于优先级。
在您的第一个示例中,由于 = 运算符的优先级高于 ,,因此您实际上并未为变量分配列表,您所做的更像是 ($a = "b"), ("c"),它实际上与字符串“c”。事实上,它是在 void 上下文中调用的。启用警告后,由于此操作不会完成任何操作,Perl 会尝试通过以下消息警告您您可能不是故意这样做的:Useless use of a constant in void context。
现在,当您尝试将列表存储到标量(或在标量上下文中使用列表)时,您希望 Perl 做什么?它不会存储列表的长度,这只是数组的一种行为。因此,它必须存储列表中的值之一。虽然我知道这在规范上是不正确的,但这个例子与实际情况非常接近。
my @animals = ("cow", "sheep", "llama");
my $return;
foreach my $animal (@animals) {
$return = $animal;
}
print $return;
因此你得到了列表的最后一个元素(典型的区别是前面的值从来没有被存储然后被覆盖,但是逻辑是相似的)。
有一些方法可以将看起来像列表的东西存储在标量中,但这涉及到引用。在perldoc perlreftut 中了解更多信息。
希望这能让事情变得更清楚一些。最后我要说,在你掌握 Perl 的优先规则之前,为列表和函数的参数加上显式括号永远不会有什么坏处。