Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if subroutine exists in Perl

Tags:

perl

I would like to check if a subroutine exists before calling it. For example:

use warnings;
use strict;

my @names=qw (A B);

for (@names) {
  my $sub=\&{"print$_"};
  if (exists &{$sub}) {
    &$sub();
  }
}

sub printA {
  print "hello A\n";
}

However this code does not work. It gives error:

Undefined subroutine &main::printB

I know that I can use eval,

for (@names) {
  my $sub=\&{"print$_"};
  eval {
    &$sub();
  };
  if ($@) {
    print "$_ does not exist..\n";
  }
}

This is fine, but it would be nice to know why the first code did not work?

like image 529
Håkon Hægland Avatar asked Aug 25 '14 12:08

Håkon Hægland


3 Answers

You're trying to make a reference before knowing whether or not the sub exists. Check that first using the name of the subroutine in the call to exists.

use strict;
use warnings;

foreach (qw(A B)) {
    my $name = 'print' . $_;
    if (exists &{$name}) {
        my $s = \&{$name};
        $s->();
    }
}

sub printA {
    print "hello A"
}
like image 187
Michael Carman Avatar answered Oct 24 '22 06:10

Michael Carman


my $sub = main->can("print$_");
if ($sub) {
  $sub->();
}

From perldoc

can checks if the object or class has a method called METHOD . If it does, then it returns a reference to the sub. If it does not, then it returns undef. This includes methods inherited or imported by $obj , CLASS , or VAL .

like image 21
mpapec Avatar answered Oct 24 '22 06:10

mpapec


if you change the code to:

for (@names) {
  my $sub="print$_";
  no strict 'refs';
  if (exists &{$sub}) {
    &$sub;
  }
}

The method will call only if it exists.

like image 24
Jens Avatar answered Oct 24 '22 06:10

Jens