【问题标题】:Ternary producing different results than If [duplicate]三元产生的结果与 If [重复] 不同
【发布时间】:2021-02-23 00:18:32
【问题描述】:

编辑:对于遇到此问题的任何人,我发现在https://perldoc.perl.org/perlop#Conditional-Operator 的 perldoc 中几乎逐字记录了这一点

在编写一个简单的子例程时,我发现使用三元运算符总是得到不正确的结果,但使用更简单的 if 语句得到正确的结果。我确信有一个解释,但我根本没有看到它。

当输入以下输入时:

my @input = (4, 5, 7, 8, 1, 2, 3, 0);
sum_square_even_root_odd(\@input);

结果应该是 91.61。

以下(使用三进制)结果为 175.61。

sub sum_square_even_root_odd {
    my ($nums) = @_;
    my $sum = 0;
    map { $_ % 2 ? $sum+= sqrt $_ : $sum += $_ ** 2 } @{$nums};
    return sprintf('%.2f', $sum) + 0;
};

然而,当简单地更改为 if 语句时,结果是预期的

sub sum_square_even_root_odd {
    my ($nums) = @_;
    my $sum = 0;
    map { if( $_ % 2 ) { $sum+= sqrt $_ } else { $sum += $_ ** 2 } } @{$nums};
    return sprintf('%.2f', $sum) + 0;
};

有人可以解释为什么会这样吗?我假设一个我没想到的值会偷偷溜进 $_,但我不确定为什么。

谢谢!

【问题讨论】:

  • 看来+= 运算符正在运行三元版本中的成功和失败案例。也许其他人可以准确解释原因——无论哪种方式,我都不会在map 中添加副作用。考虑来自List::Utilsum 函数。
  • 感谢您的洞察力。这可能是一个优先问题,但如果是,我会对如何解决它感兴趣。我在没有导入任何模块的情况下尝试了这个挑战,否则我绝对会简单地使用 List::Util。

标签: perl operator-precedence ternary


【解决方案1】:

事实上,这是一个优先问题。诊断优先级问题的方法是B::Deparse:

$ perl -MO=Deparse,-p -e 'map { $_ % 2 ? $sum+= sqrt $_ : $sum += $_ ** 2 } @ARGV'
map({((($_ % 2) ? ($sum += sqrt($_)) : $sum) += ($_ ** 2));} @ARGV);
-e syntax OK

啊哈,: 的优先级高于其右侧的 +=。要做到你的意思,请在三元运算的最后一个子句上使用括号:

$_ % 2 ? $sum+= sqrt $_ : ($sum += $_ ** 2)

【讨论】:

  • 或者更好,只是 $sum+= $_ % 2 ? sqrt $_ : $_ ** 2
  • @DaveMitchell 当然!我不知道为什么我把赋值放在三元而不是三元放在赋值里!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2014-08-23
  • 1970-01-01
  • 2015-04-24
  • 1970-01-01
相关资源
最近更新 更多