perl 如何检查一个参数是否是一个子程序?

ltskdhd1  于 2023-05-01  发布在  Perl
关注(0)|答案(2)|浏览(201)

如何测试给定的参数是否是子例程?
例如:

sub foo {
    my $bar = shift;
    if (is_subroutine($bar)) {
        return &$bar();
    }
    return 0;
}

我会把这个叫做:

foo(sub { print "Hi!" }); # prints "Hi!"
foo(123); # Nothing

我该怎么做?

qvk1mo1f

qvk1mo1f1#

核心Scalar::Util中提供了一些使用引用的工具。

use Scalar::Util qw(reftype);

my $cr = sub { say "hi @_" };

say reftype $cr;  #--> CODE

reftype返回一个变量的undef,该变量不是一个引用,所以首先测试它

sub is_subroutine {
    my $rt = reftype $_[0];
    return defined $rt and $rt eq 'CODE'
}

(but如果这是只用于短子像在问题中那么没有必要为另一个子)
在这种情况下,使用ref可能会更简单,因为它返回一个空字符串作为非引用,所以您可以直接执行以下操作

if (ref $var eq 'CODE')

除非,也就是说,可能有bless-ings混合在其中,比如一个受祝福的代码引用或一个充当子例程的对象,对于这些对象,ref只返回类名,而reftype返回底层类型。
许多Scalar::Util函数(沿着其他函数)可以在较新的Perl中使用实验性核心builtin:: pragma/namespace,包括reftype(v5.36)

jm81lzqq

jm81lzqq2#

您可以尝试使用&{...}将标量解引用为子例程,然后检查结果是否存在。

if (exists &{$bar}) {
  ...
}

此外,$bar()不是调用存储在标量引用中的子例程的有效语法。您需要编写&{$bar}()$bar->()(后者是前者的sugar)

相关问题