(编辑)TL; DR :我的问题是,尽管Win32 API定义的是真实的整数常量(如平台SDK header 中一样),而Win32 Perl包装器将它们定义为subs。从而引起一线解析的误解。
在单线测试对Win32::MsgBox
的调用时,我感到以下困惑:给出MsgBox
的可能参数是消息,用于选择按钮类型(值0..5)和消息框的标志的总和。图标“常量”(MB_ICONSTOP
,...)和标题
调用perl -MWin32 -e"Win32::MsgBox world, 4+MB_ICONQUESTION, hello"
可以得到预期的结果
而看起来相似的代码perl -MWin32 -e"Win32::MsgBox world, MB_ICONQUESTION+4, hello"
是错误的
我首先尽管这是由于缺少括号,但是添加一些perl -MWin32 -e"Win32::MsgBox (world, MB_ICONQUESTION+4, hello)"
会得出完全相同的错误结果。
我尝试与一位同事一起使用以下代码进行更深入的研究并显示传递给函数调用的参数(因为MB_xxx
常数实际上是子变量)
>perl -Mstrict -w -e"sub T{print $/,'called T(#'.join(',',@_).'#)'; 42 }; print $/,'results:', join ' ,', T(1), T+1, 1+T"
输出
called T(#1#)
called T(##)
called T(#1,43#)
results:42 ,42
但是我不明白为什么在传递给
join()
的列表中将args T+1, 1+T
解析为T(1, 43)
...
最佳答案
B::Deparse
进行救援:
C:>perl -MO=Deparse -MWin32 -e"Win32::MsgBox world, MB_ICONQUETION+4, hello"
use Win32;
Win32::MsgBox('world', MB_ICONQUESTION(4, 'hello'));
-e syntax OK
C:>perl -MO=Deparse -MWin32 -e"Win32::MsgBox world, 4+MB_ICONQESTION, hello"
use Win32;
Win32::MsgBox('world', 4 + MB_ICONQUESTION(), 'hello');
-e syntax OK
第一种情况下的
MB_ICONQUESTION
调用被认为是带有参数+4, 'hello'
的函数调用。在第二种情况下,它被视为不带参数的函数调用,并且添加了4个参数。它似乎不是一个常数,而是一个函数。在源代码中,我们对此进行了验证:
sub MB_ICONQUESTION { 0x00000020 }
它是一个返回
32
(二进制的00100000
,表示已设置的位)的函数。就像Sobrique指出的那样,这是一个标志变量,因此您不应使用加法运算,而应使用按位逻辑和/或运算符。在您的情况下,它仅接受任何参数并忽略它们。如果您期望一个常数,这会有点令人困惑。
在您的实验案例中,该语句
print $/,'results:', join ' ,', T(1), T+1, 1+T
被解释
print $/,'results:', join ' ,', T(1), T(+1, (1+T))
因为执行从右到左
1+T = 43
T +1, 43 = 42
T(1) = 42
因为plus
+
的precedence比逗号,
高,而一元+
甚至更高。为了消除歧义,您需要使用括号来阐明优先级:
print $/,'results:', join ' ,', T(1), T()+1, 1+T
# ^^-- parentheses
通常,应该始终在子程序调用中使用括号。在
perldoc perlsub
中,有4种调用符号:NAME(LIST); # & is optional with parentheses.
NAME LIST; # Parentheses optional if predeclared/imported.
&NAME(LIST); # Circumvent prototypes.
&NAME; # Makes current @_ visible to called subroutine.
在我看来,只有第一个是透明的,而另一个则有点模糊。
关于perl - (4 + sub)等于(sub + 4)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30211089/