Как мне получить подпись подпрограммы во время выполнения?

#perl #metaprogramming #signature #subroutine #subroutine-prototypes

#perl #метапрограммирование #подпись #подпрограмма #подпрограмма-прототипы

Вопрос:

Perl предоставляет API через CORE::prototype , который позволяет вам получить прототип. Это дополнительно задокументировано Sub::Util , который является документированным методом для работы с подразделениями,

Sub::Util::prototype ,

Возвращает прототип заданной $code ссылки, если она есть, в виде строки. Это то же самое, что и CORE::prototype оператор; он включен здесь просто для симметрии и полноты с другими функциями.

Однако я нигде не вижу ничего о том, как получить подписи во время выполнения? Делает ли perl это доступным?

Комментарии:

1. Прототип влияет на то, как анализируется вызов sub, и, следовательно, должен быть известен за пределами sub. Подпись, как и остальная часть тела подраздела, не обязательно должна быть известна за пределами подраздела. Таким образом, нет механизма самоанализа, кроме прохождения операций (как это делает Deparse)

Ответ №1:

Это очень … непрямой, но удаляющий подраздел и анализирующий код подписи.

 sub foo ($bar) { return 0 }

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

# contents of foo:
# BEGIN {${^WARNING_BITS} = "x10x01x00x00x00x50x04x00x00x00x00x00x00x55x50x55x50x51x01"}
# 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'/ amp;amp;
        $foo[3] =~ /Too many arguments/ amp;amp;
        $foo[4] =~ /Too few arguments/) {
    @sig = ();
    $n = 5;
    do {
        ($sig) = $foo[$n] =~ /my (Ww ) = /;
        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. Он указал мне на эту работу от ноября 2019 года, которая начинается с «Signature introspection API».