Perl 如何在运行时获取子例程的签名?

Perl 如何在运行时获取子例程的签名?,perl,metaprogramming,signature,subroutine,subroutine-prototypes,Perl,Metaprogramming,Signature,Subroutine,Subroutine Prototypes,Perl通过CORE::prototype提供了一个API,它允许您获得一个原型。这在Sub::Util中有进一步的记录,这是一种用于使用Sub的记录方法 , 以字符串形式返回给定的$code引用的原型(如果有)。这与CORE::prototype操作符相同;这里包含它只是为了和其他函数对称和完整 但是,我没有看到任何关于如何在运行时获取的信息?perl是否提供此功能?来自irc.freenode.net/#perl 15:03没有用于此的perl级api 那简直是个老板。他向我指出了“签名

Perl通过
CORE::prototype
提供了一个API,它允许您获得一个原型。这在
Sub::Util
中有进一步的记录,这是一种用于使用Sub的记录方法

,

以字符串形式返回给定的
$code
引用的原型(如果有)。这与
CORE::prototype
操作符相同;这里包含它只是为了和其他函数对称和完整

但是,我没有看到任何关于如何在运行时获取的信息?perl是否提供此功能?

来自irc.freenode.net/#perl

15:03没有用于此的perl级api


那简直是个老板。他向我指出了“签名内省API”路径的起点。这目前是不可能的,原因与传统的参数解析(
my($foo,$bar)=@;
)不是相同的:它是子例程的内部


以前有人建议添加这样的内容,但目前看来不太可能。。。间接的,但将sub分解并解析签名代码

sub foo ($bar) { return 0 }

use B::Deparse;
$foo = B::Deparse->new->coderef2text(\&foo);

# contents of foo:
# BEGIN {${^WARNING_BITS} = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x00\x55\x50\x55\x50\x51\x01"}
# use feature 'signatures';
# die sprintf("Too many arguments for subroutine at %s line %d.\n", (caller)[1, 2]) unless @_ <= 1;
# die sprintf("Too few arguments for subroutine at %s line %d.\n", (caller)[1, 2]) unless @_ >= 1;
# my $bar = $_[0];
# return 0;

@foo = split /\n/, $foo;
if ($foo[2] =~ /use feature 'signatures'/ &&
        $foo[3] =~ /Too many arguments/ &&
        $foo[4] =~ /Too few arguments/) {
    @sig = ();
    $n = 5;
    do {
        ($sig) = $foo[$n] =~ /my (\W\w+) = /;
        push @sig,$sig if $sig;
        $n++;
    } while ($sig);
    print "Signature is (", join(",",@sig), ")\n";
}
sub foo($bar){return 0}
使用B::Deparse;
$foo=B::Deparse->new->coderef2text(\&foo);
#《食物条例》的内容:
#开始{${^WARNING\U BITS}=“\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x00\x55\x50\x51\x01”}
#使用特征“签名”;
#die sprintf(“子例程在%s行%d处的参数太多。\n”,(调用者)[1,2]),除非@uU4=1;
#我的$bar=$\u0];
#返回0;
@foo=split/\n/,$foo;
如果($foo[2]=~/使用功能“签名”/&&
$foo[3]=~/参数太多/&&
$foo[4]=~/参数太少/){
@sig=();
$n=5;
做{
($sig)=$foo[$n]=~/my(\W\W+)=/;
按@sig,$sig如果$sig;
$n++;
}而(港币),;
打印“签名是(“,加入(“,”,@sig),”)\n”;
}

原型会影响对sub的调用的解析方式,因此必须在sub之外知道。签名,就像sub主体的其余部分一样,不需要在sub之外知道。因此,除了遍历ops之外,没有内省机制(就像Deparse一样)
sub foo ($bar) { return 0 }

use B::Deparse;
$foo = B::Deparse->new->coderef2text(\&foo);

# contents of foo:
# BEGIN {${^WARNING_BITS} = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x00\x55\x50\x55\x50\x51\x01"}
# use feature 'signatures';
# die sprintf("Too many arguments for subroutine at %s line %d.\n", (caller)[1, 2]) unless @_ <= 1;
# die sprintf("Too few arguments for subroutine at %s line %d.\n", (caller)[1, 2]) unless @_ >= 1;
# my $bar = $_[0];
# return 0;

@foo = split /\n/, $foo;
if ($foo[2] =~ /use feature 'signatures'/ &&
        $foo[3] =~ /Too many arguments/ &&
        $foo[4] =~ /Too few arguments/) {
    @sig = ();
    $n = 5;
    do {
        ($sig) = $foo[$n] =~ /my (\W\w+) = /;
        push @sig,$sig if $sig;
        $n++;
    } while ($sig);
    print "Signature is (", join(",",@sig), ")\n";
}