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

Raw*_*ler 3 perl

如何测试给定参数是否是子程序?

例如:

sub foo {
    my $bar = shift;
    if (is_subroutine($bar)) {
        return &$bar();
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我会这样称呼它:

foo(sub { print "Hi!" }); # prints "Hi!"
foo(123); # Nothing
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

zdi*_*dim 7

核心Scalar::Util中给出了一些处理引用的工具

use Scalar::Util qw(reftype);

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

say reftype $cr;  #--> CODE
Run Code Online (Sandbox Code Playgroud)

返回的变量不是引用,因此首先测试该reftype变量undef

sub is_subroutine {
    my $rt = reftype $_[0];
    return defined $rt and $rt eq 'CODE'
}
Run Code Online (Sandbox Code Playgroud)

(但如果这仅在问题中的短子中使用,则不需要另一个子)

那么在这种情况下使用ref可能会更简单,因为它返回一个空字符串作为非引用,所以你可以这样做

if (ref $var eq 'CODE')
Run Code Online (Sandbox Code Playgroud)

也就是说,除非可能bless混合有 -ings,例如受祝福的代码引用或充当子例程的对象,其ref仅返回类的名称,而reftype返回基础类型。

许多Scalar::Util函数(以及其他函数)都可以通过较新 Perls 中的实验核心内置::reftype pragma/namespace 获得,包括(v5.36)