Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Alternative ways to fully qualify subroutine names

by bobf (Monsignor)
on Feb 04, 2006 at 20:21 UTC ( [id://527987]=perlquestion: print w/replies, xml ) Need Help??

bobf has asked for the wisdom of the Perl Monks concerning the following question:

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!

Replies are listed 'Best First'.
Re: Alternative ways to fully qualify subroutine names
by idsfa (Vicar) on Feb 04, 2006 at 20:56 UTC

    Package::Alias, perhaps?

    use Package::Alias shortname => 'very::long::packagename';

    Under the hood, this module is just using typeglobs to alias the namespaces together.


    The intelligent reader will judge for himself. Without examining the facts fully and fairly, there is no way of knowing whether vox populi is really vox dei, or merely vox asinorum. — Cyrus H. Gordon
Re: Alternative ways to fully qualify subroutine names
by ikegami (Patriarch) on Feb 04, 2006 at 20:34 UTC
    the more subs I import the harder it becomes to keep track of where they are all from

    You could import the sub to a different name:

    *vlp_func = \&Very::Long::Package::func;

    Update: The following is a means of doing the above with a large number of functions:

    use warnings; use strict; sub import_func { my ($src_name, $dst_name) = @_; if (not defined $dst_name) { $dst_name = (split(/::/, $src_name))[-1]; } if (index($dst_name, '::') < 0) { $dst_name = caller() . '::' . $dst_name; } my $src_func_ref = do { no strict 'refs'; \&$src_name }; my $dst_glob_ref = do { no strict 'refs'; \*$dst_name }; *$dst_glob_ref = $src_func_ref; } sub Foo::Bar::func { print("Hello World!\n"); } import_func('Foo::Bar::func', 'fb_func'); fb_func(); # Calls Foo::Bar::func

    To import multiple functions at once, you can use

    import_func("Foo::Bar::$_", "fb_$_") foreach qw( func moo bla );
Re: Alternative ways to fully qualify subroutine names
by Tanktalus (Canon) on Feb 04, 2006 at 20:59 UTC
    my $sub = $pkg->can('foo'); $sub->('param'); # or simply ... $pkg->can('foo')->('param');

    Is this a good idea? Probably not. I'd have to wonder why you want to do this first.

Re: Alternative ways to fully qualify subroutine names
by dakkar (Hermit) on Feb 05, 2006 at 14:26 UTC

    Apart from using can (which is a great way), you can also do:

    package A; sub b { print "called A::b\n"; } package main; my $pack='A'; { no strict 'refs'; &{"${pack}::b"}(); }

    That is, creating a soft-ref to the sub on-the-fly.

    -- 
            dakkar - Mobilis in mobile
    

    Most of my code is tested...

    Perl is strongly typed, it just has very few types (Dan)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://527987]
Approved by idsfa
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2024-04-19 19:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found