Perl 内置的内联文档?
我遇到了一种无法直观地禁止警告的情况,因为perl正在调用内置函数。e、 gPerl 内置的内联文档?,perl,Perl,我遇到了一种无法直观地禁止警告的情况,因为perl正在调用内置函数。e、 g use strict; use warnings; { no warnings 'substr'; # no effect foo(substr('123', 4, 6)); # out of range but shouldn't emit a warning } sub foo { my $s = shift; # warning reported here # d
use strict;
use warnings;
{
no warnings 'substr'; # no effect
foo(substr('123', 4, 6)); # out of range but shouldn't emit a warning
}
sub foo {
my $s = shift; # warning reported here
# do something
}
运行此代码会导致
substr outside of string at c:\temp\foo.pl line 10.
为了抑制警告,我必须将no warnings'substr'
移动到函数内部
sub foo {
no warnings 'substr'; # works here, but there's no call to substr
my $s = shift; # no warnings here
# do something
}
我可以看到对substr
的调用是通过perl-MO=Terse
LISTOP (0x27dcaa8) leave [1]
OP (0x27a402c) enter
COP (0x27dcac8) nextstate
BINOP (0x27dcb00) leaveloop
LOOP (0x27dcb20) enterloop
LISTOP (0x27dcb68) lineseq
COP (0x27dcb88) nextstate
UNOP (0x27dcbc0) entersub [5] # entry point for foo
UNOP (0x27dcbf4) null [148]
OP (0x27dcbdc) pushmark
LISTOP (0x27dcc48) substr [4] # substr gets called here
OP (0x27dcc30) null [3]
SVOP (0x27dcc84) const [6] PV (0x2319944) "123"
SVOP (0x27dcc68) const [7] IV (0x2319904) 4
SVOP (0x27dcc14) const [8] IV (0x231944c) 6
UNOP (0x27dcca0) null [17]
PADOP (0x27dccf4) gv GV (0x2318e5c) *foo
是否在任何地方记录了此优化器行为perlsub
只提到常量函数的内联。考虑到警告被报告在错误的行中,并且无警告
在调用的词法范围内不起作用,我倾向于将其报告为一个bug,尽管我想不出如何在保持优化的同时合理地修复它
注意:此行为是在Perl 5.16.1中观察到的。这是一个记录在案的行为(在中): 字符串外部的substr (W substr),(F)您试图引用指向 在一根绳子的外面。也就是说,偏移量的绝对值为 大于字符串的长度。请参阅perlfunc中的“substr”。 如果substr用于左值上下文(如所示),则此警告是致命的 赋值的左侧,或作为 示例) 我的 将呼叫更改为
foo(my $o = substr('123', 4, 6));
使警告消失
将no warnings
移动到sub中不会改变我的行为。你有什么Perl版本?(此处为5.14.4)
我用于测试的代码:
#!/usr/bin/perl
use strict;
use warnings;
$| = 1;
print 1, foo(my $s1 = substr('abc', 4, 6));
print 2, bar(my $s2 = substr('def', 4, 6));
{
no warnings 'substr';
print 3, foo(my $s3 = substr('ghi', 4, 6));
print 4, bar(my $s4 = substr('jkl', 4, 6));
print 5, bar(substr('mno', 4, 6)); # Stops here, reports line 12.
print 6, foo(substr('pqr', 4, 6));
}
print "ok\n";
sub foo {
my $s = shift;
}
sub bar {
no warnings 'substr';
my $s = shift;
}
更新:
我在5.10.1中得到了相同的行为,但在5.20.1中,行为与您所描述的一样。正如您从B::Terse中看到的,
substr
不是内联的
$ perl -MO=Concise,-exec -e'f(substr($_, 3, 4))'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark s
4 <#> gvsv[*_] s
5 <$> const[IV 3] s
6 <$> const[IV 4] s
7 <@> substr[t4] sKM/3 <-- The substr operator is evaluated first.
8 <#> gv[*f] s/EARLYCV
9 <1> entersub[t5] vKS/TARG <-- The sub call second.
a <@> leave[1 ref] vKP/REFC
-e syntax OK
子程序参数在左值上下文中求值,因为在Perl[1]中子程序参数总是通过引用传递
子字符串操作在访问神奇标量时发生
$ perl -E'$x = "abc"; $r = \substr($x, 0, 1); $x = "def"; say $$r;'
d
这样做是为了允许substr(…)=“abc”代码>
这可能是使用与以下类似的语言记录的:“@
的元素被别名化为子例程参数。”
好奇。我正在运行5.16.1;那不是致命的。复制对foo
的调用会导致两个警告。@MichaelCarman:你说得对。在5.20.1中测试,它不会死亡,并在foo
中报告警告。看起来行为在5.16中有所改变。perl5160delta说,如果左值只从读取,而不是写入,那么它现在只是一个警告,就像右值substr
一样。显然,perldiag没有更新以匹配。无论如何,消息的严重性是相切的。主要问题是对substr
的调用首先是内联的。@MichaelCarman:但是,它们似乎是相关的,因为旧版本在正确的行报告了警告。“”。substr(…)
比my$temp=substr(…)
更简单、更容易,因为它没有内联substr
返回一个神奇的值,该值包含作为左值调用时传递给substr
的操作数(例如,作为sub的参数)。子字符串操作在访问神奇值时发生。这样做是为了允许substr(…)=“abc”代码>例如perl-e'$=“abc”;my$r=\substr($\u0,1)$_=“def”;说$$r;'代码>打印d
@ikegami:我想你找到了真正的答案;请添加您的评论作为一个。我在辩论一个博士补丁<代码>@
别名导致在左值上下文中解释substr
调用是很微妙的。我针对当前行为提交了。这不是一个bug。//文档已经明确提到了这种情况,所以我不确定您想要什么样的文档更改foreach循环的列表和sub/方法调用的参数都是左值,因为Perl总是通过引用(“别名”)传递。e、 g.perl-e'for($x){$\u=“abc”}比如说$x;'
和perl-E'sub{$\u0]=“abc”}->($x);假设$x'
@ikegami:bug是无警告的'substr'
在触发它的substr
调用出现的词法范围内没有效果。smacks head我不确定为什么我将O
输出解释为执行顺序而不是树。我想我是走错了路,因为“substr out of string”警告被报告发生在my$s=shift
行上,这意味着对substr
的调用被列在那里作为某种模糊的优化,以节省调用开销,我再也找不到回去的路了。叹息
$ perl -E'sub f { $_[0] = "def"; } $x = "abc"; f($x); say $x;'
def
$ perl -E'$x = "abc"; $r = \substr($x, 0, 1); $x = "def"; say $$r;'
d