=和,Perl中的运算符

=和,Perl中的运算符,perl,Perl,请解释这种明显不一致的行为: $a = b, c; print $a; # this prints: b $a = (b, c); print $a; # this prints: c =运算符的优先级高于,。 逗号运算符丢弃它的左参数并返回右参数 请注意,逗号运算符的行为因上下文而异。发件人: 二进制“,”是逗号运算符。在里面 标量上下文它计算其左 参数,将该值丢弃,然后 评估其正确的论点并 返回该值。这就像 C的逗号运算符 在列表上下文中,它只是列表 参数分隔符,并插入两者 将它的参数放

请解释这种明显不一致的行为:

$a = b, c;
print $a; # this prints: b

$a = (b, c);
print $a; # this prints: c

=
运算符的优先级高于

逗号运算符丢弃它的左参数并返回右参数

请注意,逗号运算符的行为因上下文而异。发件人:

二进制“,”是逗号运算符。在里面 标量上下文它计算其左 参数,将该值丢弃,然后 评估其正确的论点并 返回该值。这就像 C的逗号运算符

在列表上下文中,它只是列表 参数分隔符,并插入两者 将它的参数放入列表中。这些 参数也从左开始计算 向右


由于eugene的回答似乎给OP留下了一些问题,我试图以此为基础进行解释:

$a = "b", "c";
print $a;
这里左边的参数是
$a=“b”
,因为
=
的优先级高于
将首先计算它。之后,
$a
包含
“b”

正确的参数是
“c”
,我很快就会返回

此时,当您打印
$a
时,它显然是在将
b
打印到屏幕上

$a = ("b", "c");
print $a;
这里,由于括号的优先级较高,将首先计算术语
(“b”、“c”)
。它返回
“c”
,并将其分配给
$a

所以在这里您可以打印
“c”

此处
$a
包含“b”,而
$var
包含“c”


一旦你得到了优先规则,这是完全一致的,因为eugene和mugen已经用很好的例子很好地回答了这个问题,我将设置一些概念,然后问OP的一些概念问题,看看它是否有助于阐明一些Perl概念

第一个概念是sigils
$
@
的意思(这里我们不讨论
%
@
表示多个项目(称为“这些东西”)<代码>$表示一个项目(称为“这个东西”)。要获取数组
@a
的第一个元素,可以执行
$first=$a[0]
,获取最后一个元素:
$last=$a[-1]
。注意:不是
@a[0]
@a[-1]
。您可以通过执行
@shorter=@longer[1,2]
进行切片

第二个概念是void、scalar和list上下文之间的区别。Perl有使用容器(标量、数组等)的上下文的概念。一个简单的方法是,如果您将列表(我们将得到这个)存储为数组
@array=(“奶牛”、“绵羊”、“骆驼”)
,那么我们将数组存储为标量
$size=@array
,我们将得到数组的长度。我们还可以通过使用
scalar
操作符(如
print scalar@array
)强制执行此行为。为了清楚起见,我将再说一次:标量上下文中的数组(不是列表)将返回,而不是元素(就像列表那样),而是数组的长度

请记住,在使用
$
标志之前,您只需要一个项目,即
$first=$a[0]
。这样,您就知道您处于标量上下文中。现在,当您调用
$length=@array
时,您可以清楚地看到您正在标量上下文中调用数组,因此您可以在列表上下文中触发数组的特殊属性,从而获得其长度

这还有一个很好的特性,可以测试数组中是否有元素<代码>如果@array,则打印“@array包含项目”;除非@array,否则打印“@array为空”。if/除非测试强制数组上的标量上下文,因此if看到的是数组的长度,而不是数组的元素。由于除零外,所有数值均为“truthy”,因此,如果数组长度非零,则if
@array
语句的计算结果为true,您将得到print语句

Void context意味着忽略某些操作的返回值。在void上下文中,一个有用的操作可能类似于递增<代码>$n=1$n++;打印$n$n++(返回后的增量)处于无效上下文中,因为其返回值“1”未被使用(存储、打印等)

第三个概念是列表和数组之间的区别。列表是一组有序的值,数组是一个容器,其中包含一组有序的值。例如,在使用
sort
而不首先存储结果后,您可以在体操中看到不同之处(例如,尝试
pop sort{$a cmp$b}@array
,这不起作用,因为pop不作用于列表,而只作用于数组)

现在我们可以问,当您尝试示例时,您希望Perl在这些情况下做什么?正如其他人所说,这取决于优先顺序

在第一个示例中,由于
=
运算符的优先级高于
,您实际上没有为变量分配列表,因此您执行了类似于
($a=“b”),((“c”)
的操作,这实际上与字符串“c”无关。事实上,它是在void上下文中调用的。在启用警告的情况下,由于此操作无法完成任何操作,Perl会尝试警告您,您可能不是有意这样做的:在void上下文中无用地使用常量

现在,当您尝试将列表存储到标量(或在标量上下文中使用列表)时,您希望Perl做什么?它不会存储列表的长度,这只是数组的一种行为。因此,它必须存储列表中的一个值。虽然我知道这在规范上是不正确的,但这个例子非常接近实际情况

my @animals = ("cow", "sheep", "llama");
my $return;
foreach my $animal (@animals) {
  $return = $animal;
}
print $return;
因此,您将得到列表的最后一个元素(典型的区别是,前面的值从未存储过,然后被覆盖,但是逻辑是相似的)

有一些方法可以存储一个看起来像标量中的列表的东西,但这涉及引用。阅读更多关于这方面的文章my @animals = ("cow", "sheep", "llama"); my $return; foreach my $animal (@animals) { $return = $animal; } print $return;
perl -MO=Deparse,-p -e'$a = a, b;print $a'
(($a = 'a'), '???');
print($a);
perl -MO=Deparse,-p -e'$a = (a, b);print $a'
($a = ('???', 'b'));
print($a);