Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Getting module to call importer's function

by jredburn (Sexton)
on Sep 22, 2004 at 20:56 UTC ( [id://393046]=perlquestion: print w/replies, xml ) Need Help??

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

I would like to have a module with exported functions (there may be a class-based solution to this problem which I'd be very open to, as well) that has a number of different scripts which use it. So say we have a module M with an exported function x. What I'd like is to be able to call x in a script S with use M;. So we execute M::x. I'd like to define x something like this:
sub x { return unless &_x; ...; &_x; }
where _x is a function in S. Is this possible? Right now it looks for _x in M, which is not where it is, obviously. I would like to have M have no knowledge of the various scripts that will end up using it.

Replies are listed 'Best First'.
Re: Getting module to call importer's function
by ikegami (Patriarch) on Sep 22, 2004 at 21:05 UTC

    Like this?

    sub x { my $func = do { no strict 'refs'; *{caller() . '::_x'}{CODE} }; die() unless defined $func; &$func; # or &$func(...); }

    Test code:

Re: Getting module to call importer's function
by etcshadow (Priest) on Sep 22, 2004 at 21:06 UTC
    I think that:
    sub x { my $package = caller; return unless UNIVERSAL::can($package, "_x"); ... eval "${package}::_x"; die $@ if $@; }
    Is what you're looking for.
    ------------ :Wq Not an editor command: Wq

      That's potentially too smart by half.

      sub x { my $package = caller(); my $sub = $package->can( '_x' ); return unless defined $sub; $sub->( @_ ); }
Re: Getting module to call importer's function
by BrowserUk (Patriarch) on Sep 22, 2004 at 21:26 UTC

    Why not just pass a reference to the callback sub?

    package M; use strict; require Exporter; our @ISA = qw[ Exporter ]; our @EXPORT = qw[ x ]; sub x{ my( $sub ) = @_; &$sub; } 1;
    #! perl -slw use strict; use M; sub _x{ print __PACKAGE__ . "_x() called" } x( \&_x ); __END__ P:\test>393046 main_x() called

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      The problem is that I'm calling x from an external library so I don't have that freedom. You guys got me on the right track though, thanks much!
Re: Getting module to call importer's function
by fglock (Vicar) on Sep 22, 2004 at 21:12 UTC

    How about:

    use strict; package M; sub x { my $caller_package = shift; print "Caller: $caller_package\n"; $caller_package->_x(); } package main; sub _x { my $class = shift; print "$class _x\n"; } main->M::x();

    output:

    Caller: main main _x

    update: added "shift" in _x - thanks ikegami.

      Note: The above has the side effect of passing an extra argument to _x. Probably acceptable.
        Yep, got this working. Is there a way to call the function in a different context so as not to have to stick a dinky shift; at the start of _x? I'm trying some of the other discussed options, but can't get them working with passing parameters to _x.
Re: Getting module to call importer's function
by borisz (Canon) on Sep 22, 2004 at 21:05 UTC
    Update:
    Ups, I misunderstand the question. The other answers are much better.
    Yes, use the Exporter module to export functions in your namespace. perldoc Exporter
    Boris

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2024-04-19 17:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found