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

Hello monks,

I've question about dispatching to a module's method when two modules have the same method name. The following is a example of the coding I'm trying to achieve:

package Module1; use strict; use Exporter qw(import); our @EXPORT = qw(main); sub main { do_something(); } 1; package Module2; use strict; use Exporter qw(import); our @EXPORT = qw(main); sub main { do_something2(); } 1; script.pl my $query = get_param('page') || 'main'; my %pages = ( main => \&main, # to go to Module1 main another_page => \&main, #to go to Module2 main );
I would like the name "main" to be dispatched to Module1's "main" method and "another_page" to be dispatched to Module2's "main". The easy way out is to give Module2's "main" a different name. But if there's a conflict of method names, is there a way to unambiguously call a module's method?

Hope my question is clear and many thanks in advance.

Replies are listed 'Best First'.
Re: Dispatcher to module's method
by AnomalousMonk (Archbishop) on Dec 14, 2013 at 04:41 UTC

    Every subroutine is defined in the symbol table (or namespace) of a package, the default package being main. A subroutine can always be invoked or referenced using a fully-qualified subroutine name that includes the package. The following example does not cover the complete process of defining a standalone module, which you seem to understand, but should be enough to illustrate the principle of using a fully-qualified subroutine name. See perlmod.

    >perl -wMstrict -le "package Module1; ;; sub main { print qq{hi from main($_[0]) in package }, __PACKAGE__; } ;; package Module2; ;; sub main { print qq{hi from main($_[0]) in package }, __PACKAGE__; } ;; package main; ;; my %pages = ( PG_1 => \&Module1::main, PG_2 => \&Module2::main, ); ;; my $pg = 'PG_2'; $pages{$pg}->(42); " hi from main(42) in package Module2

    Update: Note that it's usually a Bad Idea to define a function with the same name as a very important global namespace, i.e., main. It is quite possible to keep everything straight, but you risk giving yourself a terrible headache.

      Many thanks for your excellent reply!

Re: Dispatcher to module's method
by 2teez (Vicar) on Dec 14, 2013 at 08:49 UTC

    Hi Anonymous,
    ...to a module's method when two modules have the same method name...
    But if there's a conflict of method names, is there a way to unambiguously call a module's method?...


    Though you have been given a great answer, I consider it not over "stressed" to say your requirements taste like an Object-Oriented in IMHO.
    Since, the first two principle stated in perlobj answers thus:

    1. An object is simply a data structure that knows to which class it belongs.
    2. A class is simply a package. A class provides methods that expect to operate on objects.

    So, awakening the Old dragon of OOP in Perl ( Yes, I know the "new" beasts ( Moose and it's different cousins ) are good extension of the Perl 5 object system ), one can do:
    package Module1; sub main { my $obj = shift; my $class = { name => __PACKAGE__, }; return bless $class, $obj; } package Module2; sub main { my $obj = shift; my $class = { name => __PACKAGE__, }; return bless $class, $obj; } package main; my $an1 = Module1->main(); print $an1->{name}, $/; my $an2 = Module2->main(); print $an2->{name}, $/; ## And if you must use your dispatch table ## you can do my %dispatch = ( main => Module1->main(), another_page => Module2->main(), ); print "Am in ", $dispatch{main}{name}, $/; print "Am in ", $dispatch{another_page}{name};

    NOTE:
    All emphasis mine, to note my line of thought ( I hope, I didn't misinterpret the OP question)
    both use warnings and strict were used though not stated.
    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me