文档说逗号运算符比赋值=运算符具有更高的优先级,这与 Perl 中特别不同,因此我们可以在某些上下文中删除括号。
这允许我们做这样的事情:
my @array = 1, 2, 3;
Run Code Online (Sandbox Code Playgroud)
我不明白的是为什么要这样做:
sub test() { return 1, 2 }
my ($a, $b);
$a, $b = test();
Run Code Online (Sandbox Code Playgroud)
$b[1 2]在$a没有值的情况下被分配。
虽然我假设以下内容是等效的,因为逗号运算符比赋值更严格。
($a, $b) = test();
Run Code Online (Sandbox Code Playgroud)
Raku 的语义有很多微妙之处,我想我对 Perl 的思考太多了。
就像 raiph 在评论中所说的那样,我最初的假设是逗号运算符比赋值运算符具有更高的优先级,这是错误的。这是由于运算符优先级表的呈现存在问题,该表没有按优先级顺序显示运算符。这解释了我的示例中 Raku 的实际行为。
运算=符本身始终是项目赋值级别,比逗号更严格。但是,它可以应用“子优先级”,这就是它与后面的表达式中的任何其他中缀进行比较的方式。考虑之前解析的术语=,并且:
Scalar,该运算=符的工作方式与任何其他项目赋值优先级运算符一样,它比以下项的优先级更严格,,考虑一些情况(首先,它不会影响任何事情):
$foo = 42; # $ sigil, so item assignment precedence after
@foo = 1; # @ sigil, so list assignment precedence after
@foo[0] = 1; # postcircumfix (indexing operator) means list assignment after...
$foo[0] = 1; # ...always, even in this case
Run Code Online (Sandbox Code Playgroud)
如果我们左边有一个变量,右边有一个列表,那么:
@foo = 1, 2; # List assignment into @foo two values
$foo = 1, 2; # Assignment of 1 into $foo, 2 is dead code
Run Code Online (Sandbox Code Playgroud)
这些适用于=初始化程序(在my $var声明之后)。这意味着:
loop (my $i = 0, my $j = $end; $i < $end; $i++, $j--) {
...
}
Run Code Online (Sandbox Code Playgroud)
会导致$i被分配0和$j被分配$end。
实际上,该规则意味着我们可以对数组和散列变量进行无括号初始化,同时仍然具有标量初始化列表,如loop。
转向问题中的例子。首先,这个:
($a, $b) = test();
Run Code Online (Sandbox Code Playgroud)
解析单个术语,然后遇到=. 比较任何后续中缀时的优先级将是列表前缀(比 更宽松,)。然而,这里不再有中缀,所以这并不重要。
在这种情况下:
sub test() { return 1, 2 }
my ($a, $b);
$a, $b = test();
Run Code Online (Sandbox Code Playgroud)
优先级解析器先看到,中缀,然后再看到=中缀。中缀=本身比逗号更紧密(项目分配优先级);子优先级仅对在之后解析的中缀可见=(这里没有)。
请注意,如果不是这样,并且优先级转移应用于整个表达式,那么:
loop (my $i = 0, my @lagged = Nil, |@values; $i < @values; $i++) {
...
}
Run Code Online (Sandbox Code Playgroud)
最终不会分组为(my $i = 0), (my @lagged = Nil, |@values),而是分组为(my $i = 0, my @lagged) = Nil, |@values,这是相当不那么有用的。