Whi*_*ist 1 perl parsing side-effects operators
当我在测试中获得一个奇怪的结果时,我正在为 C 制作一个运算符优先级和结合性表,对于 Perl 来说,这是同样奇怪的先验行为。
幂**运算符是右关联的,这意味着表达式是从右到左计算的。
显然,它可以正确地处理算术表达式,但奇怪的是,它不会通过打印函数调用产生预期的结果。
我期望这个输出321
$ perl -E 'print("1") ** print("2") ** print("3"); say ""'
123
Run Code Online (Sandbox Code Playgroud)
但它产生123
用户定义的函数也会发生这种情况:
$ perl -E 'sub my_print { print $_[0] } my_print(1) ** my_print(2) ** my_print(3); say ""'
123
Run Code Online (Sandbox Code Playgroud)
更奇怪的是,
$ perl -E 'sub my_print { say $_[0]; $_[0] } say my_print(2) ** my_print(2) ** my_print(4);'
2
2
4
65536
Run Code Online (Sandbox Code Playgroud)
当我们定义一个有副作用的函数时print,它也会返回一个值。算术表达式的结果具有正确的期望值,并且按照运算符结合性定义的顺序进行求值,但print仍然不符合运算符结合性。
就好像有两个评估顺序。
man perlguts和中解释的“评估顺序传递”期间op.c)。我假设这不是一个错误,而是一个功能。如果这是一个错误,那么它早就被发现了。
所以这给我带来了实际的问题: 这种行为的合理性是什么? 以及 它是如何实施的?。(意味着使用哪些数据结构以及在哪个编译时间阶段发生这种情况)。
如果我认为某处存在 AST 级别队列是对的,那么调用按什么顺序排队print?
EDIT1: 作为额外的精度,我知道 I/O 期间涉及队列,但这并没有改变 I/O 操作通常按程序的评估顺序排队的事实,而不是任意从左到右的顺序程序文本的正确顺序。
您混淆了操作数求值顺序和运算符优先级/关联性。
运算符结合性决定了如果
X ** Y ** Z // 2 ** 2 ** 3, for example
Run Code Online (Sandbox Code Playgroud)
方法
( X ** Y ) ** Z // ( 2 ** 2 ) ** 3 = 64
Run Code Online (Sandbox Code Playgroud)
或者
X ** ( Y ** Z ) // 2 ** ( 2 ** 3 ) = 256
Run Code Online (Sandbox Code Playgroud)
正如您提到的,**是右结合的,所以它意味着后者。
X它与、Y、Z和Y ** Z相对于彼此求值的顺序无关。只要 和Y在Z之前求值Y ** Z,无论这四个表达式的计算顺序如何,上面的结果都会产生相同的结果。
可以得出一些结论。如前所述,Y显然Z需要先进行评估Y ** Z。但是如果没有这样的要求[1] ,并且文档[2]中没有明确的相反声明,则可以按照编译器选择的顺序对运算符进行评估。
另一个例子是短路运算符必须先评估其左侧操作数,然后再评估其右侧操作数。
逗号运算符保证按顺序计算每个操作数。