简体   繁体   中英

How to check if a Perl scalar can be treated as a subroutine?

I have an API that originally took just a plain constant integer, but I am extending it so it can instead be computed when used by passing a subroutine reference instead. To keep backwards compatibility, I'm testing if it's a code reference:

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

but I realized that excludes objects that act as subroutines. Something like this:

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

I could just try to call it inside an eval block, but then would have to carefully check $@ to determine if it failed because it wasn't a subroutine reference (thus falling back to it being a simple scalar) vs. the called subroutine failed for some reason (error should be propagated).

In this case, of course, since the old value was a non-reference, I could just presume any reference is callable, but I'd like a general solution (as I've used this approach before when it used to be a hashref). Is there a simple and reliable way to test if a scalar is “executable”?

You can check by attempting to dereference it, but not run it, as a subroutine.

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

In this case you don't care what the error is, just whether one occurred. \\&$ref is sufficient, but by assigning the result back to $ref you can avoid invoking the overload a second time when you call that coderef. Localizing $@ is just for politeness.

As used in my Autoload::AUTOCAN module , with original credit to haarg.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM