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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With