Search code examples
perl

How can I check if a parameter is a subroutine?


How can I test if a given parameter is a subroutine?

For example:

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

I'd call this like:

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

How can I do this?


Solution

  • Some tools to work with references are given in the core Scalar::Util

    use Scalar::Util qw(reftype);
    
    my $cr = sub { say "hi @_" };
    
    say reftype $cr;  #--> CODE
    

    The reftype returns undef for a variable which isn't a reference so test for that first

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

    (but if this is used only in a short sub like in the question then there's no need for another sub)

    Then using ref may be simpler in this case as it returns an empty string for non-reference so you may be able to just do

    if (ref $var eq 'CODE')
    

    Unless, that is, there could be bless-ings mixed in, like a blessed code reference or an object acting as a subroutine, for which ref returns merely the class's name while reftype returns the underlying type.

    Many of Scalar::Util functions (along with yet others) are available with the experimental core builtin:: pragma/namespace in newer Perls, including reftype (v5.36)