http://qs321.pair.com?node_id=527987

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):

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)