perl – 内置内联的文档?

我遇到一种情况,我不能以直观的方式禁止警告,因为perl内置了一个内置函数调用.例如
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
}

我可以看到,通过传递代码通过perl -MO = Terse来调用substr是内联的

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只提到不断的功能内联.鉴于警告正在以错误的方式报告,并且在呼叫的词汇范围内没有警告不起作用,因此我倾向于将其作为错误报告,尽管我不能想到如何合理地固定,同时保持优化.

注意:在Perl 5.16.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

当substr被称为左值上下文时,substr返回一个包含传递给substr的操作数的神奇标量.

$perl -MDevel::Peek -e'$_ = "abcdef"; Dump(${\ substr($_,4) })'
SV = PVLV(0x2865d60) at 0x283fbd8
  REFCNT = 2
  FLAGS = (GMG,SMG)          <--- Gets and sets are magical.
  IV = 0                          GMG: A function that mods the scalar
  NV = 0                               is called before fetches.
  PV = 0                          SMG: A function is called after the
  MAGIC = 0x2856810                    scalar is modified.
    MG_VIRTUAL = &PL_vtbl_substr
    MG_TYPE = PERL_MAGIC_substr(x)
  TYPE = x
  TARGOFF = 3                      <--- substr's second arg
  TARGLEN = 4                      <--- substr's third arg
  TARG = 0x287bfd0                 <--- substr's first arg
  FLAGS = 0              
  SV = PV(0x28407f0) at 0x287bfd0  <--- A dump of substr's first arg
    REFCNT = 2
    FLAGS = (POK,IsCOW,pPOK)
    PV = 0x2865d20 "abcdef"\0
    CUR = 6
    LEN = 10
    COW_REFCNT = 1

子例程参数在lvalue上下文中进行求值,因为Perl [1]中的子程序参数始终通过引用传递.

$perl -E'sub f { $_[0] = "def"; }  $x = "abc"; f($x); say $x;'
def

当访问魔法标量时,发生子串操作.

$perl -E'$x = "abc"; $r = \substr($x,1); $x = "def"; say $$r;'
d

这样做可以让substr(…)=“abc”;

>这可能是使用类似于以下的语言记录的:“@_的元素被别名到子例程参数.

相关文章

1. 如何去重 #!/usr/bin/perl use strict; my %hash; while(...
最近写了一个perl脚本,实现的功能是将表格中其中两列的数据...
表的数据字典格式如下:如果手动写MySQL建表语句,确认麻烦,...
巡检类工作经常会出具日报,最近在原有日报的基础上又新增了...
在实际生产环境中,常常需要从后台日志中截取报文,报文的形...
最近写的一个perl程序,通过关键词匹配统计其出现的频率,让...