如何检查Perl标量是否可以视为子例程?

时间:2019-05-29 21:13:12

标签: perl reference closures operator-overloading

我有一个最初只使用一个普通常量整数的API,但是我对其进行了扩展,以便在使用时可以通过传递子例程引用来计算它。为了保持向后兼容性,我正在测试它是否是代码参考:

'CODE' eq ref($var)
    ? $var->()
    : $var;

但是我意识到不包括充当子例程的对象。像这样:

package Foo {
    sub new { bless {}, 'Foo' }
    use overload '&{}' => sub { sub { "Hello, world." } };
}

我可以尝试在eval块中调用它,但是随后必须仔细检查$@以确定它是否失败了,因为它不是子例程引用(因此回退到它)是一个简单的标量)与调用的子例程由于某种原因而失败(应该传播错误)。

当然,在这种情况下,由于旧值是一个非引用,因此我可以假定任何引用都是可调用的,但是我想要一个通用解决方案(因为我以前曾经使用过这种方法,是一个hashref)。是否有一种简单可靠的方法来测试标量是否“可执行”?

1 个答案:

答案 0 :(得分:5)

您可以尝试通过取消引用而不是将其作为子例程运行来进行检查。

my $is_code = ref $ref && do { local $@; eval { $ref = \&$ref; 1 } };

在这种情况下,您不必关心错误是什么,而只关心是否发生错误。 \&$ref就足够了,但是通过将结果分配回$ref,可以避免在调用该代码引用时再次调用重载。本地化$@只是出于礼貌。

my Autoload::AUTOCAN module中使用的相同,但要归功于haarg。