为啥在 Perl 中 'print (52-80)*42' 与 'print 42*(52-80)' 不同?

Posted

技术标签:

【中文标题】为啥在 Perl 中 \'print (52-80)*42\' 与 \'print 42*(52-80)\' 不同?【英文标题】:Why is 'print (52-80)*42' different than 'print 42*(52-80)' in Perl?为什么在 Perl 中 'print (52-80)*42' 与 'print 42*(52-80)' 不同? 【发布时间】:2011-04-17 21:48:05 【问题描述】:

Perl:: 什么是:

1. (52-80)*42
2. 42*(52-80)

回答:

1. -28
2. -1176

为什么?

请尽情地解释/证明这一点!

#!/usr/bin/perl
use strict;
print 42*(52-80) , "\n";
print ((52-80)*42) , "\n";
print (52-80)*42 , "\n";
print "\n";
my $i=(52-80)*42;
print $i, "\n";

输出:

> -1176
> -1176-28
> -1176

【问题讨论】:

鉴于您的输出中没有足够的换行符,我认为这不是您实际运行的代码,是吗? @Ben 试试看。它确实产生了该输出。提示:这不是数学或优先级问题,而是括号解析问题... 标题和问题当然是错误的。 -28 的结果取决于更大的代码 sn-p。 你错过了关键的use warnings; 我们在Learning Perl 中专门讨论了这个问题。人们可能会认为阅读这本书是在浪费时间,但我想知道人们不阅读它浪费了多少时间。 【参考方案1】:

如果您添加use warnings;,您将获得:

print (...) interpreted as function at ./test.pl line 5.
Useless use of a constant in void context at ./test.pl line 5

【讨论】:

【参考方案2】:

感谢 Perl 古怪的解析规则(哦 Perl,你疯了!),这些语句:

print ((52-80)*42) , "\n";
print (52-80)*42 , "\n";

被解释为好像它们是写的:

(print ((52-80)*42)), "\n";
(print (52-80))*42, "\n";

这就是为什么您最终会在一行中看到-1176-28,并且缺少预期的空白行。 Perl 看到 (print-expr), "\n"; 并简单地丢弃换行符而不是打印它。

【讨论】:

任何其他选择在其他情况下都一样古怪。除非您真正的抱怨是所有参数都应该始终使用括号?【参考方案3】:

Alex Howansky 暗示的警告意味着

print (52-80)*42 , "\n"

被解析为

(print(52-80)) * 42, "\n"

也就是说,一个列表包含 (1) 函数 print(-28) 的结果的 42 倍,以及 (2) 包含换行符的字符串。 (1) 的副作用是将值 -28(不带换行符)打印到标准输出。

如果您需要打印以括号开头的表达式,解决方法是在其前面加上+

print +(52-80)*42, "\n"         #  ==> -1176

【讨论】:

或者只是打印到一个文件句柄,就像任何 sane.... 等一下,我正要在同一个句子中使用 sane 和 Perl。我在想什么? 或者,如果您不确定如何解释它们,就不要使用隐式括号。记住,伙计们,速记不是强制性的。 这不是一个列表(如 void context 警告所示)。 这是一个列表(你可以通过逗号来判断)。无效上下文警告是关于列表第二个元素中无用的"\n"

以上是关于为啥在 Perl 中 'print (52-80)*42' 与 'print 42*(52-80)' 不同?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Perl 在 ClearCase 中找不到我的文件?

Perl:为啥在循环中声明(我的)变量会更慢?

xampp中的perl文件夹有啥用,为啥它包含在xampp中? [关闭]

为啥 PowerShell(使用 Perl)在简单的打印语句中删除双引号?

为啥 Perl 文件 glob() 不能在标量上下文中的循环之外工作?

Perl 的等价于 PHP 的 print_r() 是啥?