【问题标题】:How do I get the signature of a subroutine in runtime?如何在运行时获取子程序的签名?
【发布时间】:2020-09-10 19:27:29
【问题描述】:

Perl 通过CORE::prototype 提供了一个API,可以让你得到一个原型。 Sub::Util 进一步记录了这一点,这是使用 subs 的记录方法,

Sub::Util::prototype,

返回给定$code 引用的原型(如果有的话)作为字符串。这与CORE::prototype 运算符相同;在这里包含它只是为了与其他功能的对称性和完整性。

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

【问题讨论】:

  • 原型会影响对 sub 的调用的解析方式,因此必须在 sub 之外知道。签名,就像 sub 主体的其余部分一样,不需要在 sub 之外知道。因此,除了遍历操作(就像 Deparse 那样)之外,没有自省机制

标签: perl metaprogramming signature subroutine subroutine-prototypes


【解决方案1】:

这是非常...间接的,但是解析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";
}

【讨论】:

    【解决方案2】:

    目前这是不可能的,原因与传统参数解析 (my ($foo, $bar) = @_;) 不可行的原因相同:它在子例程内部。

    之前有人建议添加这样的东西,但目前似乎不太可能。

    【讨论】:

      【解决方案3】:

      来自 irc.freenode.net/#perl,

      15:03 < Grinnz> there's no perl level api for that
      

      这几乎是一个 perl 半兽人。他将我指向this work from Nov 2019,它从“签名自省 API”的路径开始。

      【讨论】:

        猜你喜欢
        • 2019-09-13
        • 2016-09-24
        • 1970-01-01
        • 1970-01-01
        • 2015-05-07
        • 2011-08-23
        • 1970-01-01
        • 2012-01-31
        • 2020-09-06
        相关资源
        最近更新 更多