为什么在Perl中'print (52-80)*42'和'print 42*(52-80)'不同?

3

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

1
鉴于你的输出中没有足够的换行符,我不认为这是你实际运行的代码,对吧? - Ben Voigt
4
尝试一下。它确实会生成完全相同的输出。提示:这不是数学或优先级问题,而是括号解析问题... - John Kugelman
3
标题和问题当然是错误的。结果-28取决于更大的代码片段。 - Ben Voigt
5
你缺少了关键的 use warnings; - ysth
1
我们在《学习 Perl》一书中特别讨论了这个问题。有些人可能会认为读这本书是浪费时间,但我想知道他们不阅读它会浪费多少时间。 - brian d foy
显示剩余5条评论
3个回答

25

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

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

17

Alex Howansky所提到的警告意味着

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

被解析为

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

也就是说,一个包含以下内容的列表 (1) 42次函数 print(-28) 的结果,和 (2) 包含换行符的字符串。 (1) 的副作用是将值 -28(没有换行符)打印到标准输出。

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

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

或者只需像任何明智的人一样将其打印到文件句柄中...等等,我刚才要在同一个句子中使用“明智”和“Perl”。我在想什么? - Ben Voigt
4
如果你不确定隐含的括号会被怎样解释,最好就不要使用它们。记住,朋友们,缩写并非强制性的。 - sorpigal
这不是一个列表(正如无效上下文警告所示)。 - ysth
这是一个列表(通过逗号可以看出)。void上下文警告是关于列表的第二个元素中无用的"\n"。 - mob

6
感谢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";,并且只是舍弃了换行符而没有打印它。

5
在其他情况下,任何其他选择都会和这种选择一样古怪。除非您真正的抱怨是所有参数周围应该始终需要括号? - ysth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接