Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

comment on

( [id://3333] : superdoc . print w/replies, xml ) Need Help??

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!


In reply to Alternative ways to fully qualify subroutine names by bobf

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.