perl - 需要帮助了解 Perl 5 如何解析引用相同变量的复合赋值语句

标签 perl variable-assignment parentheses

我需要了解如何评估这个简单的表达式,因为结果与我预期的不一样。

我对 Perl 很陌生,但我认为我有足够的理解来解释这个看似简单的片段的结果。显然我错过了一些东西。
我已经使用 Deparse 来查看 Perl 是如何处理表达式的,而 Deparse 并没有改变我已有的括号。

$i = 12;
$i = (($i /= 2) + ($i = 100));
print $i;

根据我的理解,结果应该是 106,假设表达式按照括号指示的顺序进行评估,并且看起来应该是这样。我会认为:
$i 首先除以 2,从而将 6 分配给 $i,得到值 6。然后将 100 分配给 $i,100 是第二个表达式的结果。 6 + 100 = 106,我认为最终会分配给 $i。
相反,它会打印 "200"。

在 PHP 中,同样的代码确实会产生“106”,这让我相信这与表达式的某些部分被解释为列表有关,或者与 Perl 一样精彩的东西有关。
迫不及待地想知道我做错了什么。

最佳答案

到目前为止,大多数语言都没有定义当您在单个表达式中读取和写入相同的值变量时会发生什么。 Perl 也不异常(exception)。您发布的表达式没有定义的结果。

这记录在 perlop 中:

modifying a variable twice in the same statement will lead to undefined behavior. Avoid statements like:

    $i = $i ++;
    print ++ $i + $i ++;


发生的事情是 $i /= 2$i = 100两者都返回 $i —不是 $i 的值, 但是 $i本身——所以你最终会做$i + $i而不是 6 + 100 .你不能指望这种行为。此外,Perl 碰巧先计算加法的左操作数,然后再计算右操作数——这是你不能指望的其他事情——所以 $i100是时候执行加法了。

如果有人想鬼混,这里是当前 perl 时发生的事情的再现。评估 OP 的代码:
use strict;
use warnings;
use feature qw( say );
use experimental qw( refaliasing declared_refs );

my $i = 12;

my @ST;  # Stack
{                                      \$ST[@ST] = \( $i                    ); }
{                                      \$ST[@ST] = \( 2                     ); }
{ \my ($lhs, $rhs) = \splice(@ST, -2); \$ST[@ST] = \( $lhs /= $rhs          ); }
{                                      \$ST[@ST] = \( 100                   ); }
{                                      \$ST[@ST] = \( $i                    ); }
{ \my ($rhs, $lhs) = \splice(@ST, -2); \$ST[@ST] = \( $lhs = $rhs           ); }
{ \my ($lhs, $rhs) = \splice(@ST, -2); \$ST[@ST] = \( my $sum = $lhs + $rhs ); }
{                                      \$ST[@ST] = \( $i                    ); }
{ \my ($rhs, $lhs) = \splice(@ST, -2); \$ST[@ST] = \( $lhs = $rhs           ); }

say $i;  # 200

如果你使用 Devel::Peek 的 Dump ,您会注意到上面的大多数变量具有相同的地址。它们就是我们在 Perl 行话中所说的“别名”。

以下使用引用代替(尽管实际上没有创建实际引用):
use strict;
use warnings;
use feature qw( say );

my $i = 12;

my @ST;  # Stack
{                                         push @ST, \( $i                          ); }
{                                         push @ST, \( 2                           ); }
{ my ($lhs_p, $rhs_p) = splice(@ST, -2);  push @ST, \( $$lhs_p /= $$rhs_p          ); }
{                                         push @ST, \( 100                         ); }
{                                         push @ST, \( $i                          ); }
{ my ($rhs_p, $lhs_p) = splice(@ST, -2);  push @ST, \( $$lhs_p = $$rhs_p           ); }
{ my ($lhs_p, $rhs_p) = splice(@ST, -2);  push @ST, \( my $sum = $$lhs_p + $$rhs_p ); }
{                                         push @ST, \( $i                          ); }
{ my ($rhs_p, $lhs_p) = splice(@ST, -2);  push @ST, \( $$lhs_p = $$rhs_p           ); }

say $i;  # 200

关于perl - 需要帮助了解 Perl 5 如何解析引用相同变量的复合赋值语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57468346/

相关文章:

perl - For 循环以匹配数组中所需的记录值

perl - 为什么 Higher Order Perl 中的 make_rand 不起作用?

c - 理解 C 中的语句

c++ - 可以初始化但不能赋值的对象

c++ - pair(const std::pair<_T1, _T2>&) 被隐式删除,因为默认定义格式不正确错误:分配 unique_ptr 映射时

javascript - javascript中根据括号分割字符串

python - 如何删除字符串中外括号之间的所有文本?

perl - 在 perl 中使用 open3 写入之前从进程读取

perl - 如何获取 perl 模块中当前启用的一组警告检查?

c++ - 是否有有助于计算括号的 C++ 函数?