为什么除法被解析为正则表达式?
Why is division parsed as regular expression?
这是我的代码的一部分:
my $suma = U::round $item->{ suma }; # line 36
$ts += $suma;
$tnds += U::round $suma /6;
}
return( $ts, $tnds );
}
sub create { #line 46
my( $c ) = shift;
my $info = $c->req->json;
my $header = @$info[0];
my $details = @$info[1];
my $agre = D::T Agreement => $header->{ agreement_id };
my( $total_suma, $total_nds ) = total( $details );
my $saldo = 0;
my $iid = @$details[0]->{ period };
my $interval = D::T Period => $iid //7; # line 58
# This is first Invoice if operator do not provide activation date
my $is_first = !$details->[0]{valid_from} && $iid && $interval;
加载此模块时出现错误:
Can't load application from file "lib/MaitreD/Controller/ManualDocument.pm line 38, near "my $interval = D::T Period => $iid /"
Unknown regexp modifier "/6" at lib/MaitreD/Controller/ManualDocument.pm line 38, at end of line
Global symbol "$pkg" requires explicit package name (did you forget to declare "my $pkg"?) at lib/MaitreD/Controller/ManualDocument.pm line 41.
...
这个间接对象调用有罪吗?
因为我在 U::round( $suma /6 )
处加上括号时没有错误
Perl 认为符号 /
是正则表达式的开始而不是除法运算符。 https://perldoc.perl.org/perlre - 您可以检查 perldoc 中的正则表达式。
您可以尝试在 6
之前添加一个空白字符,如下所示:$tnds += U::round $suma / 6;
这里有一些关于此的想法,以及一个似是而非的解释。简单再现
perl -wE'sub tt { say "@_" }; $v = 7; tt $v /3'
给我
Search pattern not terminated at -e line 1.
因此它会尝试在该子例程调用中解析正则表达式,如前所述,问题是:为什么?
在参数周围加上括号,它按预期工作。如果后面有更多参数,它也会以同样的方式失败,但如果前面有参数,它就可以工作
perl -wE'sub tt { say "@_" }; $v = 7; tt $v /3, 3' # fails the same way
perl -wE'sub tt { say "@_" }; $v = 7; tt 3, $v /3' # works
为 tt
潜艇配备原型并不会改变这一切。
错误似乎是 /
触发了 search for the closing delimiter and once it's not found 整个事情都失败了。那么为什么这被解释为正则表达式而不是除法?
似乎 tt $v
在解析中被分组,并被解释为一个 sub 及其参数,因为它们后面跟着一个 space;然后 /3
被单独使用,然后它看起来像一个正则表达式。† 这仍然会因为语法错误而失败,但也许正则表达式解析失败首先出现。
那么前面或后面的其他逗号分隔的术语之间的区别就很明显了——tt 3, ...
后面的 $v /3
是下一个参数的术语,并被解析为除法。
这还有一个问题。我尝试过的所有内置函数都没有这个问题,无论是列表运算符还是一元运算符,都有各种原型(push
、chr
、splice
等)——除了 print
,它确实有同样的问题。并且无论有无括号都失败了。
perl -wE'$v=110; say for unpack "A1A1", $v /2' #--> 5 5
perl -wE'$v=200; say chr $v /2' #--> d
perl -wE'$v=3; push @ary, $v /2; say "@ary"' #--> 1.5
perl -wE'$v = 7; say $v /3' # fails, the same way
perl -wE'$v = 7; say( $v /3 )' # fails as well, same way
不同之处在于 print
遵循“特殊”解析规则,并且允许第一个参数是文件句柄。 (此外,它没有原型,但这似乎并不重要。)
那么表达式print $v /3...
确实可以被解析为print filehandle EXPR
,而/
开头的EXPR
被解析为正则表达式。同样适用于括号。‡
所有这些都涉及一些猜测,因为我不知道解析器是如何做到的。但这显然是如何解析子程序调用的细节问题,什么(不小心?)也包括 print
。
在我看来,在(用户定义的)子例程上使用括号的明显补救措施是合理的。另一个修复是与围绕数学运算符的 spaces 保持一致,要么不在任何一侧使用它们,要么在两侧都使用它们——这也很好,即使它很痒(spaces?真的吗?)。
虽然 say( $v /3 )
存在问题,但我不知道该说些什么。
关于这个问题的更多评论。
根据问题中错误消息的文本 Unknown regexp modifier "/6"
,似乎 /
被用作结束分隔符,这与上面的示例不同。该消息中还有更多内容,尚不清楚。最后,我们确实有一个非常相似的解析问题。
至于
Is this indirect object call guilty?
我在那里没有看到间接对象调用,只有正常的子例程调用。此外,此答案中的示例显示了非常相似的行为并排除了间接对象语法。
† 另一种可能性是 $v /3
被解析为一个术语,因为它跟在(可识别的!)子例程名称 tt
之后。然后,正则表达式绑定运算符 =~
binds 比除法更紧密,这里暗示默认情况下明确尝试绑定到 $_
。
我发现这不太可能,而且它也无法解释内置函数的行为,尤其是 print
。
‡
然后可以推断出其他具有可选的无逗号第一个参数(因此没有原型)的内置函数以相同的方式进行,但我不能轻易想到任何一个。
这是我的代码的一部分:
my $suma = U::round $item->{ suma }; # line 36
$ts += $suma;
$tnds += U::round $suma /6;
}
return( $ts, $tnds );
}
sub create { #line 46
my( $c ) = shift;
my $info = $c->req->json;
my $header = @$info[0];
my $details = @$info[1];
my $agre = D::T Agreement => $header->{ agreement_id };
my( $total_suma, $total_nds ) = total( $details );
my $saldo = 0;
my $iid = @$details[0]->{ period };
my $interval = D::T Period => $iid //7; # line 58
# This is first Invoice if operator do not provide activation date
my $is_first = !$details->[0]{valid_from} && $iid && $interval;
加载此模块时出现错误:
Can't load application from file "lib/MaitreD/Controller/ManualDocument.pm line 38, near "my $interval = D::T Period => $iid /"
Unknown regexp modifier "/6" at lib/MaitreD/Controller/ManualDocument.pm line 38, at end of line
Global symbol "$pkg" requires explicit package name (did you forget to declare "my $pkg"?) at lib/MaitreD/Controller/ManualDocument.pm line 41.
...
这个间接对象调用有罪吗?
因为我在 U::round( $suma /6 )
处加上括号时没有错误
Perl 认为符号 /
是正则表达式的开始而不是除法运算符。 https://perldoc.perl.org/perlre - 您可以检查 perldoc 中的正则表达式。
您可以尝试在 6
之前添加一个空白字符,如下所示:$tnds += U::round $suma / 6;
这里有一些关于此的想法,以及一个似是而非的解释。简单再现
perl -wE'sub tt { say "@_" }; $v = 7; tt $v /3'
给我
Search pattern not terminated at -e line 1.
因此它会尝试在该子例程调用中解析正则表达式,如前所述,问题是:为什么?
在参数周围加上括号,它按预期工作。如果后面有更多参数,它也会以同样的方式失败,但如果前面有参数,它就可以工作
perl -wE'sub tt { say "@_" }; $v = 7; tt $v /3, 3' # fails the same way
perl -wE'sub tt { say "@_" }; $v = 7; tt 3, $v /3' # works
为 tt
潜艇配备原型并不会改变这一切。
错误似乎是 /
触发了 search for the closing delimiter and once it's not found 整个事情都失败了。那么为什么这被解释为正则表达式而不是除法?
似乎 tt $v
在解析中被分组,并被解释为一个 sub 及其参数,因为它们后面跟着一个 space;然后 /3
被单独使用,然后它看起来像一个正则表达式。† 这仍然会因为语法错误而失败,但也许正则表达式解析失败首先出现。
那么前面或后面的其他逗号分隔的术语之间的区别就很明显了——tt 3, ...
后面的 $v /3
是下一个参数的术语,并被解析为除法。
这还有一个问题。我尝试过的所有内置函数都没有这个问题,无论是列表运算符还是一元运算符,都有各种原型(push
、chr
、splice
等)——除了 print
,它确实有同样的问题。并且无论有无括号都失败了。
perl -wE'$v=110; say for unpack "A1A1", $v /2' #--> 5 5
perl -wE'$v=200; say chr $v /2' #--> d
perl -wE'$v=3; push @ary, $v /2; say "@ary"' #--> 1.5
perl -wE'$v = 7; say $v /3' # fails, the same way
perl -wE'$v = 7; say( $v /3 )' # fails as well, same way
不同之处在于 print
遵循“特殊”解析规则,并且允许第一个参数是文件句柄。 (此外,它没有原型,但这似乎并不重要。)
那么表达式print $v /3...
确实可以被解析为print filehandle EXPR
,而/
开头的EXPR
被解析为正则表达式。同样适用于括号。‡
所有这些都涉及一些猜测,因为我不知道解析器是如何做到的。但这显然是如何解析子程序调用的细节问题,什么(不小心?)也包括 print
。
在我看来,在(用户定义的)子例程上使用括号的明显补救措施是合理的。另一个修复是与围绕数学运算符的 spaces 保持一致,要么不在任何一侧使用它们,要么在两侧都使用它们——这也很好,即使它很痒(spaces?真的吗?)。
虽然 say( $v /3 )
存在问题,但我不知道该说些什么。
关于这个问题的更多评论。
根据问题中错误消息的文本 Unknown regexp modifier "/6"
,似乎 /
被用作结束分隔符,这与上面的示例不同。该消息中还有更多内容,尚不清楚。最后,我们确实有一个非常相似的解析问题。
至于
Is this indirect object call guilty?
我在那里没有看到间接对象调用,只有正常的子例程调用。此外,此答案中的示例显示了非常相似的行为并排除了间接对象语法。
† 另一种可能性是 $v /3
被解析为一个术语,因为它跟在(可识别的!)子例程名称 tt
之后。然后,正则表达式绑定运算符 =~
binds 比除法更紧密,这里暗示默认情况下明确尝试绑定到 $_
。
我发现这不太可能,而且它也无法解释内置函数的行为,尤其是 print
。
‡ 然后可以推断出其他具有可选的无逗号第一个参数(因此没有原型)的内置函数以相同的方式进行,但我不能轻易想到任何一个。