Is there a way to fully qualify a subroutine with the package name in a variable but without using eval?
This is possible with OO programming, where a long class name can be replaced with a variable:
my $class = 'Very::Long::Class::Name';
$class->method;
I want to do a similar thing for non-OO subroutines, so I can add clarity to the program by fully qualifying the sub name but still keep the call to a manageable length (and without sprinkling eval everywhere). Doing this:
my $pkg = 'Very::Long::Package::Name';
$pkg::sub;
obviously doesn't work, since
$pkg::sub refers to the global variable
$sub in the
pkg namespace.
I've considered the following options (example code below):
- Fully qualify the sub call, forget about the variable
This is the standard, I guess.
- Call the sub as a method (even though it isn't one)
This seems like a Bad Idea. Also, the contents of @_ will change depending on whether it is called as a sub or as a method (in which case the class name will be the first parameter).
- Assemble the call into a string, then use eval
Eww. This may achieve the primary goal, but it really clutters things up.
- Create a reference to the sub itself (not the package)
I don't mind doing it this way, but it requires a separate ref for every sub from the same package. I'd rather create a ref (or something) to the package so I only have one variable, then append the appropriate sub name as required.
- Import the subs into the caller's namespace, forget about fully qualifying it
This is how I'm doing it now, but the more subs I import the harder it becomes to keep track of where they are all from (hence the desire to use fully qualified names).
use strict;
use warnings;
{
package very::long::packagename;
sub foo
{
print '[', join( '][', @_ ), "]\n";
return "from sub foo\n";
}
}
{
package pkg;
our $foo = "foovar\n";
}
{
package bar;
# this refers to $foo in package 'pkg'
print $pkg::foo; # foovar
# fully qualified sub call
very::long::packagename::foo( 'param' ); # [param]
# create a ref to a fully qualified sub
my $subfoo_ref = \&very::long::packagename::foo;
print $subfoo_ref->( 'param' ); # from sub foo
$subfoo_ref->( 'param' ); # [param]
# call the sub as a method
my $pkg = 'very::long::packagename';
$pkg->foo( 'param' ); # [very::long::packagename][param]
# stringify the call, use eval
my $func_str = $pkg . "::foo( 'param' );";
eval $func_str; # [param]
}
Are there other ways of doing this that are not listed above? Comments regarding best practices are also appreciated.
Thanks!