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